一、理解socket
socket正如前文所说用于进程之间的通信,相当于是操作系统的I/O的延伸。
二、建立socket
先建立一个实际的socket对象,然后再将其连接到远程服务器。
建立socket对象时包含通信类型和协议家族。通信类型包括IPv4、IPv6、IPX/SPX(Netware)和AFP(Apple文件共享)。通常使用AF_INET,即IPv4。协议家族一般包括TCP通信的SOCK_STREAM和UDP通信的SOCK_DGRAM。连接对象时需提供一个包含远程主机名或IP地址和端口号的元组。对于不知道端口号的,可通过socket库的getservbyname函数来获得,格式为:socket.getservbyname(servicename[,protocolname]),服务名和协议名(tcp,udp)。
通过socket库来建立。类似如下:
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect((‘www.baidu.com‘,80))
利用socket通信时可以用socket对象,也可以用文件对象。用socket对象的情况:读写数据时,需要协议可以详细地控制时、使用二进制协议传送固定大小数据时、数据超时需要特殊处理时,或是任何不止需要简单读写时,还有编写UDP程序时。而文件类对象一般用于面向线性的协议,只能用于TCP
socket模块的4种异常:
与一般I/O和通信问题有关的socket.error;与查询地址信息有关的socket.gaierror;与其他地址错误有关的socket.herror;与在一个socket调用settimeout()后,处理超时有关的socket.timeout
对于很多操作系统来说,又是在网络上发送数据的调用会在远程服务器收到信息前返回,因此可能有sendall成功调用返回但服务器收不到信息的情况发生。通过结束写操作后调用shutdown函数来解决。
三、总结
创建TCP客户端伪代码:
cs=socket() cs.connect() comm_loop: cs.send()/cs.recv() cs.close()
创建UDP客户端伪代码
ss=socket() ss.bind() inf_loop: cs=ss.recvfrom()/ss.sendto() ss.close()
socket对象方法:
函数 |
描述 |
服务器端套接字 | |
s.bind() | 绑定地址(主机名,端口号名)到套接字,主机名必须是本机,可以为空,代表所有地址 |
s.listen() | 开始TCP监听,参数一般为5 |
s.accept() | 被动接受TCP客户端连接,(阻塞式)等待连接 ,参数为socket对象和(host,port)元组。 |
客户端套接字 | |
s.connect() | 主动初始化TCP服务器连接,参数为(host,port) |
s.connect_ex() | 出错时返回出错码,而非抛出异常 |
公共的套接字 | |
s.recv() | 接受数据,参数为buflen |
s.send() | 发送TCP数据,参数为data |
s.sendall() |
完整发送TCP数据 |
s.recvfrom() | 接受UDP数据,接受到的结果为data和发送者地址 |
s.sendto() | 发送UDP数据,参数为data和addr |
s.getpeername() | 连接到当前套接字的远端的地址, |
s.getsockname() | 当前套接字的地址 |
s.setsockopt() | 设置指定套接字的参数 |
s.close() | 关闭套接字 |
面向模块的套接字函数 | |
s.setblocking() | 设置套接字的阻塞和非阻塞模式(0|1) |
s.settimeout() | 设置阻塞套接字操作的超时时间 |
s.gettimeout() | 得到阻塞套接字操作的超时时间 |
面向文件的套接字函数 | |
s.fileno() | 套接字的文件描述符 |
s.makefile() | 创建一个与该套接字关联的文件对象 |