[python] socket模块(TCP/IP网络编程)

本文只关心python的网络编程,并重点学习TCP/IP单元。

一、简单了解下:

1、什么是TCP/IPUDP

         TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
         UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。
        这里有一张图,表明了这些协议的关系。


       TCP/IP协议族包括运输层(传输层)、网络层、(数据)链路层。现在你知道TCP/IP与UDP的关系了吧。

2、Socket在哪里呢?
       在上图中,我们没有看到Socket的影子,那么它到底在哪里呢?还是用图来说话,一目了然。

       原来Socket在这里。


3、Socket是什么呢?
       Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

4、怎样使用socket?

       前人已经给我们做了好多的事了,网络间的通信也就简单了许多,但毕竟还是有挺多工作要做的。以前听到Socket编程,觉得它是比较高深的编程知识,但是只要弄清Socket编程的工作原理,神秘的面纱也就揭开了。
       一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。    生活中的场景就解释了这工作原理,也许TCP/IP协议族就是诞生于生活中,这也不一定。

       先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

二、socket模块函数

由于socket模块中的属性太多,可直接使用import socket ,这样能大幅缩减代码。

1、socket(family,type)

创建套接字。

套接字是计算机网络数据结构。网络化的应用程序在开始任何通讯之前都必须创建套接字。可以比作电话的插口一样,没有它就完全没办法通信。

创建TCP/IP套接字:

1 tcpsock = socket(AF_INET , SOCK_STREAM)

创建UDP/IP套接字:

1 udpsock = socket(AF_INET , SOCK_DGRAM)

AF:地址家族的缩写

SOCK_STREAM:面向连接套接字,即在通信之前一定要简历一条连接(就像跟朋友打电话)。面向连接的通信方式提供了顺序的、可靠的、不会重复的数据传输,而且也不会被加上数据边界。发送信息时,信息能被拆分成多份,没分都会到达正确的目的地,然后被重新按顺序拼装起来,传给正在等待的应用程序。

SOCK_DGRAM:无连接套接字,即无需建立连接就可以进行通讯。但此时,数据到达是顺序、可靠性及不重复性就无法保证了,数据报会保留数据边界。数据是整个发送的。使用数据报来传输数据就像快递包裹一样,不一定会按发送顺序到达,而且还有可能根本到达不了。

2、套接字对象(内建)方法

函数 描述
服务器端套接字函数
s.bind()

绑定地址(主机名,端口号)到套接字

合法端口号范围为0~65535。其中小于1024的为系统保留端口,其余的均可用

s.listen() 开始TCP监听。参数表示最多允许多少个连接同时连进来,而后边的连接就会被拒绝掉
s.accept() (阻塞式)接受连接并返回(conn,address),conn是新的套接字对象,可以用来通过连接发送和接收数据,address是另一个连接端的套接字地址
客户端套接字函数
s.connect() 连接到address处的远程套接字。有错误时出现socket.error
s.connect_ex() connect()的扩展版本,出错时返回出错码,而不是抛出异常。成功返回0
公共用途的套接字函数
s.recv(bufsize [,flags]) 接收TCP数据。bufsize指定要接收的最大数据量。flags提供有关消息的其他信息,通常忽略
s.send() 发送TCP数据
s.sendall() 完整发送TCP数据
s.recvfrom(bufsize [,flags]) 接收UDP数据。返回(data,address),data是接收数据字符串,address是发送数据的套接字地址
s.sendto(string [,flags],address) 发送UDP数据。address形式是元组,指定远程地址
s.fileno()  返回套接字的文件描述符
 s.makefile(mode[,bufsize])  创建与套接字关联的文件对象。mode中'r'表示读取,'w'表示写入,'a'表示添加,'+'表示读写,'b'表示二进制访问。
   

3、异常

error:该异常表示与套接字或者地址有关的错误。它返回一个(errno,mesg)对以及底层系统调用返回的错误。继承自IOError。

herror:表示与地址有关的错误。返回一个包含错误编号的错误消息的元祖(herrno,hmesg)。继承自error。

4、创建TCP连接实例代码

客户端

 1 import socket
 2 
 3 HOST = '192.168.1.100'                          #服务器IP
 4 PORT = 12345                                     #端口号
 5 BUFSIZ = 1024
 6 ADDR = (HOST,PORT)
 7 
 8 tcpCliSock = socket(AF_INET,SOCK_STREAM)        #创建TCP/IP套接字
 9 tcpCliSock.connect(ADDR)                        #尝试连接服务器
10 
11 while True:
12     data = input('> ')
13     if not data:
14         break
15     tcpCliSock.send(data)              #发送TCP数据
16     data = tcpCliSock.recv(BUFSIZ)     #接收TCP数据
17     if not data:
18         break
19     print(data)
20 
21 tcpCliSock.close

服务器

 1 import socket
 2 import time
 3 
 4 HOST = '192.168.1.100'
 5 PORT = 12345
 6 BUFSIZE = 1024
 7 ADDR = (HOST,PORT)
 8 
 9 tcpSerSock = socket(AF_INET,SOCK_STREAM)
10 tcpSerSock.bind(ADDR)
11 tcpSerSock.linsten(5)
12 
13 while True:
14     print('waiting for connection... ')
15     tcpCliSock,addr = tcpSerSock.accept()
16     print('...connected from : ',addr)
17     
18     while True:
19         data = tcpCliSock.recv(BUFSIZE)
20         if not data:
21             break
22         tcpSerSock.send((' [%s] %s' % (ctime(),data)))
23 
24         tcpCliSock.close()
25 tcpSerSock.close()

代码实现:

当有连接时,进入对话循环,等待客户端发送数据。如果消息为空,表示客户端已经退出,再等待下一个客户端连接。得到客户端消息后,在消息前叫一个时间戳然后返回。

要先开服务器,后开客户端。

5、创建UDP连接实例代码

客户端

 1 import socket
 2  
 3 HOST = '192.168.1.100'                          #服务器IP
 4 PORT = 12345                                     #端口号
 5 BUFSIZ = 1024
 6 ADDR = (HOST,PORT)
 7 udpCliSock = socket(AF_INET,SOCK_DGRAM)        
 8 
 9 while True:
10     data = input('> ')
11     if not data:
12         break
13     udpCliSock.sendto(data,ADDR)              #发送UDP数据
14     data,ADDR = udpCliSock.recvfrom(BUFSIZ)     #接收UDP数据
15     if not data:
16         break
17     print(data)
18     udpCliSock.close()
19 udpCliSock.close

服务器

 1 import socket
 2 import time
 3  
 4 HOST = '192.168.1.100'                          #服务器IP
 5 PORT = 12345                                     #端口号
 6 BUFSIZ = 1024
 7 ADDR = (HOST,PORT)
 8 
 9 udpSerSock = socket(AF_INET,SOCK_DGRAM)        
10 udpSerSock.bind(ADDR)
11 
12 while True:
13     print'waiting for message... '14     data,addr = udpSerSock.recvfrom(BUFSIZ)
15     udpSerSock.sendto('[%s] %s' % (ctime(,data),addr))              
16     print(' ...received from and returned to:',addr)
17 udpCliSock.close

UDP和TCP服务器的一个重要区别就是,由于数据报套接字是无连接的,所以无法把客户端连接交给另外的套接字进行后续的通讯。这些服务器知识接受消息,需要的话,给客户端返回一个结果就可以了。

服务器输出客户端信息的原因是,服务器可能会得到并回复多个客户端消息,这时,输出就可以了解系哦啊系来自那里。对于TCP服务器来说,由于客户端会创建一个连接,我们自然就知道消息来自那里了。

原文地址:https://www.cnblogs.com/zhanxiage1994/p/4109241.html