首页 > 代码库 > 网络编程之TCP编程

网络编程之TCP编程

<style type="text/css">html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video { margin: 0; padding: 0; border: 0 } body { font-family: Helvetica, arial, freesans, clean, sans-serif; font-size: 14px; line-height: 1.6; color: #333; background-color: #fff; padding: 20px; max-width: 960px; margin: 0 auto } body>*:first-child { margin-top: 0 !important } body>*:last-child { margin-bottom: 0 !important } p,blockquote,ul,ol,dl,table,pre { margin: 15px 0 } h1,h2,h3,h4,h5,h6 { margin: 20px 0 10px; padding: 0; font-weight: bold } h1 tt,h1 code,h2 tt,h2 code,h3 tt,h3 code,h4 tt,h4 code,h5 tt,h5 code,h6 tt,h6 code { font-size: inherit } h1 { font-size: 28px; color: #000 } h2 { font-size: 24px; border-bottom: 1px solid #ccc; color: #000 } h3 { font-size: 18px } h4 { font-size: 16px } h5 { font-size: 14px } h6 { color: #777; font-size: 14px } body>h2:first-child,body>h1:first-child,body>h1:first-child+h2,body>h3:first-child,body>h4:first-child,body>h5:first-child,body>h6:first-child { margin-top: 0; padding-top: 0 } a:first-child h1,a:first-child h2,a:first-child h3,a:first-child h4,a:first-child h5,a:first-child h6 { margin-top: 0; padding-top: 0 } h1+p,h2+p,h3+p,h4+p,h5+p,h6+p { margin-top: 10px } a { color: #4183C4; text-decoration: none } a:hover { text-decoration: underline } ul,ol { padding-left: 30px } ul li>:first-child,ol li>:first-child,ul li ul:first-of-type,ol li ol:first-of-type,ul li ol:first-of-type,ol li ul:first-of-type { margin-top: 0px } ul ul,ul ol,ol ol,ol ul { margin-bottom: 0 } dl { padding: 0 } dl dt { font-size: 14px; font-weight: bold; font-style: italic; padding: 0; margin: 15px 0 5px } dl dt:first-child { padding: 0 } dl dt>:first-child { margin-top: 0px } dl dt>:last-child { margin-bottom: 0px } dl dd { margin: 0 0 15px; padding: 0 15px } dl dd>:first-child { margin-top: 0px } dl dd>:last-child { margin-bottom: 0px } pre,code,tt { font-size: 12px; font-family: Consolas, "Liberation Mono", Courier, monospace } code,tt { margin: 0 0px; padding: 0px 0px; white-space: nowrap; border: 1px solid #eaeaea; background-color: #f8f8f8 } pre>code { margin: 0; padding: 0; white-space: pre; border: none; background: transparent } pre { background-color: #f8f8f8; border: 1px solid #ccc; font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px } pre code,pre tt { background-color: transparent; border: none } kbd { background-color: #DDDDDD; background-image: linear-gradient(#F1F1F1, #DDDDDD); background-repeat: repeat-x; border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD; border-style: solid; border-width: 1px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; line-height: 10px; padding: 1px 4px } blockquote { border-left: 4px solid #DDD; padding: 0 15px; color: #777 } blockquote>:first-child { margin-top: 0px } blockquote>:last-child { margin-bottom: 0px } hr { clear: both; margin: 15px 0; height: 0px; overflow: hidden; border: none; background: transparent; border-bottom: 4px solid #ddd; padding: 0 } table th { font-weight: bold } table th,table td { border: 1px solid #ccc; padding: 6px 13px } table tr { border-top: 1px solid #ccc; background-color: #fff } table tr:nth-child(2n) { background-color: #f8f8f8 } img { max-width: 100% }</style>

socket编程之TCP编程

socket是网络编程的一个抽象概念.通常我们用Socket表示"打开了一个网络连接",而打开一个Socket需要知道目标计算机的ip 地址和端口号,再指定协议即可.

在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。


客户端/服务端架构

即C/S架构,包括

1.硬件C/S架构(打印机)

2.软件C/S架构(web服务)

客户端(c端)

  • 大多数连接是可靠的TCP连接 ,创建TCP连接时,主动发起连接的叫客户端,被动响应连接的叫服务器.

举个栗子,我们把socket的过程比喻为一个打电话的过程,创建一个基于TCP链接的Socket:

import socket#导入socket模块
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#创建一个socket(拿一个电话)
phone.connect(("127.0.0.1",8080))#建立连接(拨电话)

其中,AF_INET表示指定ipv4协议,如果要更加先进的ipv6 ,可以指定 AF_INET6.目前ipv4还是主流. SOCK_STREAM指定指定面向流的TCP协议,这样一个Socket对象就创建成功.

其中("127.0.0.1",8080),前者是是服务器的ip,也可以用域名代替,后者是服务器端口号,作为服务器,ip和端口都应该是固定的.

注意("127.0.0.1",8080)是一个元祖.

建立TCP连接后,我们就可以向服务器发送请求,要求返回.

phone.send(msg.encode("utf-8"))#发送数据(对服务端说话)

TCP连接创建的是双向通道,双方都可以互相发数据.

data= http://www.mamicode.com/phone.recv(1024)#接收服务端数据(听服务端的话)"utf-8"))#显示出来

接收数据时,用recv(max)方法.其中括号指定一次最多接收的字节数.

当我们接收完数据后,调用close()方法关闭Socket,这样,一次完整的网络通信就结束了:

phone.close()#关闭连接(挂电话)

服务器(s端)


和客户端编程相比,服务器编程就要复杂一些。 服务器进程首先要绑定一个端口并监听来自客户端的连接.所以服务器会打开固定端口监听,每一个客户端连接就创建该Socket连接.由于服务器会有大量来自客户端的连接,所以,服务器要能够区分一个Socket连接是和哪个客户端绑定的。一个Socket依赖4项:服务器地址、服务器端口、客户端地址、客户端端口来唯一确定一个Socket。

首先,创建一个基于IPv4和TCP协议的Socket:

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#同上,建立socket

然后,我们要绑定监听的地址和端口.端口号需要预先指定

phone.bind(("127.0.0.1",8080))#监听端口
phone.listen(5)#开始监听(5代表传入的参数指定等待连接的最大数量)

接下来,服务端程序用一个死循环来接收客户端的连接,accept()会等待并返回一个客户端的连接

while True:
    conn,addr=phone.accept()#建立连接

然后,服务端程序用一个死循环开始接受客户端的数据,并返回数据

while True:
    conn,addr=phone.accept()#建立连接
    while True:
        try:#建立异常处理机制,当客户端断开连接时,直接退出本层接收数据的循环,返回建立连接的循环
            data=conn.recv(1024)#接收客户端数据
            if not data:break#消息为空则重复循环
            print("客户端发来的消息",data.decode("utf-8"))#打印客户端发来的数据
            conn.send("好几把炫酷!".encode("utf-8"))#返回数据给客户端
        except Exception:
            break
    conn.close()#关闭本次连接

我们从头到尾来一遍:

#服务端
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(("127.0.0.1",8080))
phone.listen(5)
print("starting")
while True:
    conn,addr=phone.accept()
    while True:
        try:
            data=conn.recv(1024)
            if not data:break
            print("客户端发来的消息",data.decode("utf-8"))
            conn.send("好几把炫酷!".encode("utf-8"))
        except Exception:
            break
    conn.close()
phone.close()

#客户端
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(("127.0.0.1",8080))
while True:
    msg=input(">>>")
    if not msg:continue
    if msg=="quit":break
    phone.send(msg.encode("utf-8"))
    data= http://www.mamicode.com/phone.recv(1024)"utf-8"))
phone.close()

小结

用TCP协议进行Socket编程在python中十分简单,对于客户端,要主动连接服务端的ip和指定端口,对于服务端,则是监听指定端口.

网络编程之TCP编程