## socket ```python socket 就是套接字: CP用主机的IP地址加上主机上的端口号做为TCP链接的端点,这种端点就叫作套接字 它是网络通讯过程当中端点的抽象表示,包含进行网络通讯必需的五种信息:链接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。 #网络通讯和链接,主要有3个参数:通讯的目的IP地址、使用的传输层协议(TCP或UDP)和使用的端口号。Socket原意是 “插座”。经过将这3个参数结合起来,与一个“插座”Socket绑定,应用层就能够和传输层经过套接字接口,区分来自不一样应用程序进程或网络链接的通讯,实现数据传输的并发服务 就是一个封装好的模块,要学习的就是模块的使用方法 socket分为两种类型 AF_UNIX : 进程间通信 AF_INET : 网络通信 需明确:关于网络协议 和socket相关概念,对于全部编程语言都是一致的,区别仅仅是各编程语言的函数名称不一样 要明确一点:不管是客户端服务器端都使用的都是socket对象 ``` ## socket内经常使用函数 ```python 服务端套接字函数 s.bind() 绑定(主机,端口号)到套接字 s.listen() 开始TCP监听 s.accept() 被动接受TCP客户的链接,(阻塞式)等待链接的到来 客户端套接字函数 s.connect() 主动初始化TCP服务器链接 s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常 公共用途的套接字函数 s.recv() 接收TCP数据 s.send() 发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完) s.sendall() 发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完) s.recvfrom() 接收UDP数据 s.sendto() 发送UDP数据 s.getpeername() 链接到当前套接字的远端的地址 s.getsockname() 当前套接字的地址 s.getsockopt() 返回指定套接字的参数 s.setsockopt() 设置指定套接字的参数 s.close() 关闭套接字 面向锁的套接字方法 s.setblocking() 设置套接字的阻塞与非阻塞模式 s.settimeout() 设置阻塞套接字操做的超时时间 s.gettimeout() 获得阻塞套接字操做的超时时间 ``` <p style="color:red">注意TCP中必须先启动服务器再启动客户端,不然客户端因为没法连接服务器,直接报错!</p> ## TCP服务端 ```python import socket ip_port=('127.0.0.1',8081)#电话卡 BUFSIZE=1024 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #买手机 s.bind(ip_port) #手机插卡 s.listen(5) #手机待机 while True: #新增接收连接循环,能够不停的接电话 conn,addr=s.accept() #手机接电话 # print(conn) # print(addr) print('接到来自%s的电话' %addr[0]) while True: #新增通讯循环,能够不断的通讯,收发消息 msg=conn.recv(BUFSIZE) #听消息,听话 print(msg,type(msg)) conn.send(msg.upper()) #发消息,说话 conn.close() #挂电话 s.close() #手机关机 ``` ## TCP客户端 ```python import socket ip_port=('127.0.0.1',8081) BUFSIZE=1024 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect_ex(ip_port) #拨电话 while True: #新增通讯循环,客户端能够不断发收消息 msg=input('>>: ').strip() if len(msg) == 0:continue s.send(msg.encode('utf-8')) #发消息,说话(只能发送字节类型) feedback=s.recv(BUFSIZE) #收消息,听话 print(feedback.decode('utf-8')) s.close() #挂电话 ``` 当客服端与服务器连接成功后,若是一方没有执行close,而是直接强行终止程序(或是遇到异常被迫终止),都会致使另外一方发送问题 linux下,不会抛出异常会致使接收数据的一方,recv方法不断的收到空消息,形成死循环 要使应用程序可以在不一样平台正常工做,那须要分别处理这两个问题 解决方案以下: ```python import socket ip_port=('127.0.0.1',8081) BUFSIZE=1024 s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.bind(ip_port) s.listen(5) while True: conn,addr=s.accept() while True: try: msg=conn.recv(BUFSIZE) #linux不会抛出异常,会接收到空消息,这里加以判断 if not msg: conn.close() break print(msg,type(msg)) conn.send(msg.upper()) except ConnectionResetError: #只要异常发生则意味着对方以及关闭了,服务器也相应的关闭该连接 conn.close() break conn.close() s.close() ``` 至此TCP通信模板程序就完成了,能够不断的接收新的连接,不断的收发消息,而且不会由于客户端强制关闭而异常退出!