python网络编程之(socket)套接字
---恢复内容开始---
套接字是计算机网络数据结构,它体现了上节中所描述的“通信端点”的概念。在任何 类型的通信开始之前,网络应用程序必须创建套接字。可以将它们比作电话插孔,没有它将 无法进行通信。
起源
套接字的起源可以追溯到 20 世纪 70 年代,它是加利福尼亚大学的伯克利版本 UNIX(称 为 BSD UNIX)的一部分。因此,有时你可能会听过将套接字称为伯克利套接字或 BSD 套接 字。套接字最初是为同一主机上的应用程序所创建,使得主机上运行的一个程序(又名一个 进程)与另一个运行的程序进行通信。这就是所谓的进程间通信(Inter Process Communication, IPC)。有两种类型的套接字:基于文件的和面向网络的。
基于文件类型的套接字家族
UNIX 套接字是我们所讲的套接字的第一个家族。
并且拥有一个“家族名字”AF_UNIX (又名 AF_LOCAL,在 POSIX1.g 标准中指定),它代表地址家族(address family):UNIX。
unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信
基于网络类型的套接字家族
第二种类型的套接字是基于网络的,它也有自己的家族名字 AF_INET,或者地址家族: 因特网。
另一个地址家族 AF_INET6 用于第 6 版因特网协议(IPv6)寻址。此外,还有其他 的地址家族,这些要么是专业的、过时的、很少使用的,要么是仍未实现的。
在所有的地址 家族之中,目前 AF_INET 是使用得最广泛的。
套接字地址:主机-端口对
如果一个套接字像一个电话插孔——允许通信的一些基础设施,那么主机名和端口号就 像区号和电话号码的组合。
然而,拥有硬件和通信的能力本身并没有任何好处,除非你知道 电话打给谁以及如何拨打电话。一个网络地址由主机名和端口号对组成,而这是网络通信所 需要的。
此外,并未事先说明必须有其他人在另一端接听;否则,你将听到这个熟悉的声音 “对不起,您所拨打的电话是空号,请核对后再拨”。你可能已经在浏览网页的过程中见过一 个网络类比,例如“无法连接服务器,服务器没有响应或者服务器不可达。”
有效的端口号范围为 0~65535(尽管小于 1024 的端口号预留给了系统)。如果你正在使 用 POSIX 兼容系统(如 Linux、Mac OS X 等),那么可以在/etc/services 文件中找到预留端口 号的列表(以及服务器/协议和套接字类型)。众所周知的端口号列表可以在这个网站中查看: http://www.iana.org/assignments/port-numbers。
socket工作原理
生活中的场景就解释了这工作原理。你和朋友通电话,有要先拨打号码,一朋友听到铃声接通电话,你们建立了连接。
然后通话相当于交流信息,然后挂断电话,结束交谈!

面向连接的套接字与无连接的套接字
1.面向连接的套接字
不管你采用的是哪种地址家族,都有两种不同风格的套接字连接。第一种是面向连接的, 这意味着在进行通信之前必须先建立一个连接,例如,使用电话系统给一个朋友打电话。这 种类型的通信也称为虚拟电路或流套接字。
面向连接的通信提供序列化的、可靠的和不重复的数据交付,而没有记录边界。这基本 上意味着每条消息可以拆分成多个片段,并且每一条消息片段都确保能够到达目的地,然后 将它们按顺序组合在一起,最后将完整消息传递给正在等待的应用程序。
实现这种连接类型的主要协议是传输控制协议(更为人熟知的是它的缩写 TCP)。为 了 创建 TCP 套接字,必须使用 SOCK_STREAM 作为套接字类型。TCP 套接字的名字 SOCK_STREAM 基于流套接字的其中一种表示。
因为这些套接字(AF_INET)的网络版本 使用因特网协议(IP)来搜寻网络中的主机,所以整个系统通常结合这两种协议(TCP 和 IP) 来进行(当然,也可以使用 TCP 和本地[非网络的 AF_LOCAL/AF_UNIX]套接字,但是很明 显此时并没有使用 IP)。
2.无连接的套接字
与虚拟电路形成鲜明对比的是数据报类型的套接字,它是一种无连接的套接字。这意味 着,在通信开始之前并不需要建立连接。此时,在数据传输过程中并无法保证它的顺序性、 可靠性或重复性。然而,数据报确实保存了记录边界,这就意味着消息是以整体发送的,而 并非首先分成多个片段,例如,使用面向连接的协议。
实现这种连接类型的主要协议是用户数据报协议(更为人熟知的是其缩写 UDP)。为 了 创建 UDP 套接字,必须使用 SOCK_DGRAM 作为套接字类型。你可能知道,UDP 套接字的 SOCK_DGRAM 名字来自于单词“datagram”(数据报)。
因为这些套接字也使用因特网协议 来寻找网络中的主机,所以这个系统也有一个更加普通的名字,即这两种协议(UDP 和 IP) 的组合名字,或 UDP/IP。
tcp协议与udp协议区别
TCP(Transmission Control Protocol)可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;电子邮件、文件传输程序。
UDP(User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。

socket()模块函数
要创建套接字,必须使用 socket.socket()函数,它一般的语法如下。
socket(socket_family, socket_type, protocol=0) #其中,socket_family 是 AF_UNIX 或 AF_INET(如前所述), #socket_type 是 SOCK_STREAM或 SOCK_DGRAM(也如前所述)。 #protocol 通常省略,默认为 0。
所以,为了创建 TCP/IP 套接字,可以用下面的方式调用 socket.socket()。
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
同样,为了创建 UDP/IP 套接字,需要执行以下语句。
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
因为有很多 socket 模块属性,所以此时使用“from module import *”这种导入方式可以 接受,不过这只是其中的一个例外。如果使用“from socket import *”,那么我们就把 socket 属性引入到了命名空间中。虽然这看起来有些麻烦,但是通过这种方式将能够大大缩短代码, 正如下面所示。
tcpSock = socket(AF_INET, SOCK_STREAM)
一旦有了一个套接字对象,那么使用套接字对象的方法将可以进行进一步的交互。
套接字对象(内置)方法
| 名称 | 描述 |
| 服务器套接字方法 | |
| s.bind() | 将地址(主机名、端口号对)绑定到套接字上 |
| s.listen() | 设置并启动 TCP 监听器 |
| s.accept() | 被动接受 TCP 客户端连接,一直等待直到连接到达(阻塞) |
| 客户端套接字方法 | |
| s.connect() | 主动发起 TCP 服务器连接 |
| s.connect_ex() | connect()的扩展版本,此时会以错误码的形式返回问题,而不是抛出一个异常 |
| 普通的套接字方法 | |
| s.recv() | 接收 TCP 消息 |
| s.recv_into()① | 接收 TCP 消息到指定的缓冲区 |
| s.send() | 发送 TCP 消息 |
| s.sendall() | 完整地发送 TCP 消息 |
| s.recvfrom() | 接收 UDP 消息 |
| s.recvfrom_into()① | 接收 UDP 消息到指定的缓冲区 |
| s.sendto() | 发送 UDP 消息 |
| s.getpeername() | 连接到套接字(TCP)的远程地址 |
| s.getsockopt() | 返回给定套接字选项的值 |
| s.setsockopt() | 设置给定套接字选项的值 |
| s.shutdown() | 关闭连接 |
| s.close() | 关闭套接字 |
| s.detach()② | 在未关闭文件描述符的情况下关闭套接字,返回文件描述符 |
| s.ioctl()③ | 控制套接字的模式(仅支持 Windows) |
| 面向阻塞的套接字方法 | |
| s.setblocking() | 设置套接字的阻塞或非阻塞模式 |
| s.settimeout()④ | 设置阻塞套接字操作的超时时间 |
| s.gettimeout()④ | 获取阻塞套接字操作的超时时间 |
| 面向文件套接字方法 | |
| s.fileno() | 套接字的文件描述符 |
| s.makefile() | 创建与套接字关联的文件对象 |
| 数据属性 | |
| s.family① | 套接字家族 |
| s.type① | 套接字类型 |
| s.proto① | 套接字协议 |
① Python 2.5 中新增。 ② Python 3.2 中新增。 ③ Python 2.6 中新增,仅仅支持 Windows 平台;POSIX 系统可以使用 functl 模块函数。 ④ Python 2.3 中新增。
Socket模块初使用
基于TCP 协议的 socket
tcp 是基于链接的 ,必须先启动server端,再去启动clien 端去链接服务端。
server端
#导入模块 import socket #实力一个sk接口 sk = socket.socket() #socket()默认TCP协议 #绑定地址,(‘ip’,端口) sk.bind(('127.0.0.1',8899)) #监听链接 sk.listen() #接收客户端链接 ,conn建立好的链接,addr客户端地址 conn,addr = sk.accept() #接收消息 ret = conn.recv(1024) print(ret) #向客户端发送消息 conn.send(b'hello') #关闭客户端套接字 conn.close() #关闭服务端套接字 sk.close()
clien端
import socket sk = socket.socket() # 创建客户端sk sk.connect(('127.0.0.1',8899)) #去链接服务端(‘ip',端口) sk.send(b'ha,ha') #向服务端发送消息 ret = sk.recv(1024) #接收消息 print(ret) sk.close() #关闭
问题:重启服务端时可能会遇到
我们可能会遇到下面的问题:

解决方法:
#加入一条socket配置,重用ip和端口 import socket from socket import SOL_SOCKET,SO_REUSEADDR sk = socket.socket() sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加 sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字 sk.listen() #监听链接 conn,addr = sk.accept() #接受客户端链接 ret = conn.recv(1024) #接收客户端信息 print(ret) #打印客户端信息 conn.send(b'hi') #向客户端发送信息 conn.close() #关闭客户端套接字 sk.close() #关闭服务器套接字(可选)
TCP 时间戳服务器
创建 TCP 服务器
server端
它是一个 TCP 服务器程序,它接受客户端发送的数据 字符串,并将其打上时间戳(格式:[时间戳]数据)并返回给客户端(“server”代表时间戳 TCP 服务器,其他文件以类似的方式命名)。
服务端
from socket import * from time import ctime #导入了 time.ctime()和 socket 模块的所有属性。 host = '127.0.0.1' #本地回环地址 port = 9000 #端口 bufsiz = 1024 #将缓冲区大小设置为 1KB addr = (host, port) tcpsk = socket(AF_INET, SOCK_STREAM) tcpsk.bind(addr) #绑定地址 tcpsk.listen(5) #listen()方法的参数是在连接被转接或拒绝之前,传入连接请求的最大数。 while True: print('waiting for connection.....') Conn,Addr = tcpsk.accept() print('...connected from:',Addr) while True: data = Conn.recv(bufsiz).decode('utf-8') print(data) if not data: break data = '[%s] %s' % (ctime(), data) Conn.send(data.encode('utf-8') ) #ctime()当前格式化时间 Conn.close() tcpsk.close()
创建 TCP 客户端
clien端
这个脚本连接到服务器,并以逐行数据的形式提 示用户。服务器则返回加了时间戳的相同数据,这些数据最终会通过客户端代码呈现给 用户。
from socket import * host = '127.0.0.1' #本地回环地址 port = 9000 #端口 bufsiz = 1024 #将缓冲区大小设置为 1KB addr = (host, port) tcpck = socket(AF_INET,SOCK_STREAM) tcpck.connect(addr) while True: data = input('>').encode('utf-8') if not data: break tcpck.send(data) data = tcpck.recv(bufsiz).decode('utf-8') if not data: break print(data) tcpck.close()
基于UDP 协议的 socket
创建UDP服务器
UDP 服务器不需要 TCP 服务器那么多的设置,因为它们不是面向连接的。除了等待传 入的连接之外,几乎不需要做其他工作。
UDP 和TCP服务器之间还有另一个显著区别,因为数据包套接字是无连接的,所以就没有为了成功的通信,而使一个客户端连接到一个独立的套接字“转换的操作”,这些服务器仅仅接受消息并有可能回复消息。
---恢复内容结束---
套接字是计算机网络数据结构,它体现了上节中所描述的“通信端点”的概念。在任何 类型的通信开始之前,网络应用程序必须创建套接字。可以将它们比作电话插孔,没有它将 无法进行通信。
起源
套接字的起源可以追溯到 20 世纪 70 年代,它是加利福尼亚大学的伯克利版本 UNIX(称 为 BSD UNIX)的一部分。因此,有时你可能会听过将套接字称为伯克利套接字或 BSD 套接 字。套接字最初是为同一主机上的应用程序所创建,使得主机上运行的一个程序(又名一个 进程)与另一个运行的程序进行通信。这就是所谓的进程间通信(Inter Process Communication, IPC)。有两种类型的套接字:基于文件的和面向网络的。
基于文件类型的套接字家族
UNIX 套接字是我们所讲的套接字的第一个家族。
并且拥有一个“家族名字”AF_UNIX (又名 AF_LOCAL,在 POSIX1.g 标准中指定),它代表地址家族(address family):UNIX。
unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信
基于网络类型的套接字家族
第二种类型的套接字是基于网络的,它也有自己的家族名字 AF_INET,或者地址家族: 因特网。
另一个地址家族 AF_INET6 用于第 6 版因特网协议(IPv6)寻址。此外,还有其他 的地址家族,这些要么是专业的、过时的、很少使用的,要么是仍未实现的。
在所有的地址 家族之中,目前 AF_INET 是使用得最广泛的。
套接字地址:主机-端口对
如果一个套接字像一个电话插孔——允许通信的一些基础设施,那么主机名和端口号就 像区号和电话号码的组合。
然而,拥有硬件和通信的能力本身并没有任何好处,除非你知道 电话打给谁以及如何拨打电话。一个网络地址由主机名和端口号对组成,而这是网络通信所 需要的。
此外,并未事先说明必须有其他人在另一端接听;否则,你将听到这个熟悉的声音 “对不起,您所拨打的电话是空号,请核对后再拨”。你可能已经在浏览网页的过程中见过一 个网络类比,例如“无法连接服务器,服务器没有响应或者服务器不可达。”
有效的端口号范围为 0~65535(尽管小于 1024 的端口号预留给了系统)。如果你正在使 用 POSIX 兼容系统(如 Linux、Mac OS X 等),那么可以在/etc/services 文件中找到预留端口 号的列表(以及服务器/协议和套接字类型)。众所周知的端口号列表可以在这个网站中查看: http://www.iana.org/assignments/port-numbers。
socket工作原理
生活中的场景就解释了这工作原理。你和朋友通电话,有要先拨打号码,一朋友听到铃声接通电话,你们建立了连接。
然后通话相当于交流信息,然后挂断电话,结束交谈!

面向连接的套接字与无连接的套接字
1.面向连接的套接字
不管你采用的是哪种地址家族,都有两种不同风格的套接字连接。第一种是面向连接的, 这意味着在进行通信之前必须先建立一个连接,例如,使用电话系统给一个朋友打电话。这 种类型的通信也称为虚拟电路或流套接字。
面向连接的通信提供序列化的、可靠的和不重复的数据交付,而没有记录边界。这基本 上意味着每条消息可以拆分成多个片段,并且每一条消息片段都确保能够到达目的地,然后 将它们按顺序组合在一起,最后将完整消息传递给正在等待的应用程序。
实现这种连接类型的主要协议是传输控制协议(更为人熟知的是它的缩写 TCP)。为 了 创建 TCP 套接字,必须使用 SOCK_STREAM 作为套接字类型。TCP 套接字的名字 SOCK_STREAM 基于流套接字的其中一种表示。
因为这些套接字(AF_INET)的网络版本 使用因特网协议(IP)来搜寻网络中的主机,所以整个系统通常结合这两种协议(TCP 和 IP) 来进行(当然,也可以使用 TCP 和本地[非网络的 AF_LOCAL/AF_UNIX]套接字,但是很明 显此时并没有使用 IP)。
2.无连接的套接字
与虚拟电路形成鲜明对比的是数据报类型的套接字,它是一种无连接的套接字。这意味 着,在通信开始之前并不需要建立连接。此时,在数据传输过程中并无法保证它的顺序性、 可靠性或重复性。然而,数据报确实保存了记录边界,这就意味着消息是以整体发送的,而 并非首先分成多个片段,例如,使用面向连接的协议。
实现这种连接类型的主要协议是用户数据报协议(更为人熟知的是其缩写 UDP)。为 了 创建 UDP 套接字,必须使用 SOCK_DGRAM 作为套接字类型。你可能知道,UDP 套接字的 SOCK_DGRAM 名字来自于单词“datagram”(数据报)。
因为这些套接字也使用因特网协议 来寻找网络中的主机,所以这个系统也有一个更加普通的名字,即这两种协议(UDP 和 IP) 的组合名字,或 UDP/IP。
tcp协议与udp协议区别
TCP(Transmission Control Protocol)可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;电子邮件、文件传输程序。
UDP(User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。

socket()模块函数
要创建套接字,必须使用 socket.socket()函数,它一般的语法如下。
socket(socket_family, socket_type, protocol=0) #其中,socket_family 是 AF_UNIX 或 AF_INET(如前所述), #socket_type 是 SOCK_STREAM或 SOCK_DGRAM(也如前所述)。 #protocol 通常省略,默认为 0。
所以,为了创建 TCP/IP 套接字,可以用下面的方式调用 socket.socket()。
tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
同样,为了创建 UDP/IP 套接字,需要执行以下语句。
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
因为有很多 socket 模块属性,所以此时使用“from module import *”这种导入方式可以 接受,不过这只是其中的一个例外。如果使用“from socket import *”,那么我们就把 socket 属性引入到了命名空间中。虽然这看起来有些麻烦,但是通过这种方式将能够大大缩短代码, 正如下面所示。
tcpSock = socket(AF_INET, SOCK_STREAM)
一旦有了一个套接字对象,那么使用套接字对象的方法将可以进行进一步的交互。
套接字对象(内置)方法
| 名称 | 描述 |
| 服务器套接字方法 | |
| s.bind() | 将地址(主机名、端口号对)绑定到套接字上 |
| s.listen() | 设置并启动 TCP 监听器 |
| s.accept() | 被动接受 TCP 客户端连接,一直等待直到连接到达(阻塞) |
| 客户端套接字方法 | |
| s.connect() | 主动发起 TCP 服务器连接 |
| s.connect_ex() | connect()的扩展版本,此时会以错误码的形式返回问题,而不是抛出一个异常 |
| 普通的套接字方法 | |
| s.recv() | 接收 TCP 消息 |
| s.recv_into()① | 接收 TCP 消息到指定的缓冲区 |
| s.send() | 发送 TCP 消息 |
| s.sendall() | 完整地发送 TCP 消息 |
| s.recvfrom() | 接收 UDP 消息 |
| s.recvfrom_into()① | 接收 UDP 消息到指定的缓冲区 |
| s.sendto() | 发送 UDP 消息 |
| s.getpeername() | 连接到套接字(TCP)的远程地址 |
| s.getsockopt() | 返回给定套接字选项的值 |
| s.setsockopt() | 设置给定套接字选项的值 |
| s.shutdown() | 关闭连接 |
| s.close() | 关闭套接字 |
| s.detach()② | 在未关闭文件描述符的情况下关闭套接字,返回文件描述符 |
| s.ioctl()③ | 控制套接字的模式(仅支持 Windows) |
| 面向阻塞的套接字方法 | |
| s.setblocking() | 设置套接字的阻塞或非阻塞模式 |
| s.settimeout()④ | 设置阻塞套接字操作的超时时间 |
| s.gettimeout()④ | 获取阻塞套接字操作的超时时间 |
| 面向文件套接字方法 | |
| s.fileno() | 套接字的文件描述符 |
| s.makefile() | 创建与套接字关联的文件对象 |
| 数据属性 | |
| s.family① | 套接字家族 |
| s.type① | 套接字类型 |
| s.proto① | 套接字协议 |
① Python 2.5 中新增。 ② Python 3.2 中新增。 ③ Python 2.6 中新增,仅仅支持 Windows 平台;POSIX 系统可以使用 functl 模块函数。 ④ Python 2.3 中新增。
Socket模块初使用
基于TCP 协议的 socket
tcp 是基于链接的 ,必须先启动server端,再去启动clien 端去链接服务端。
server端
#导入模块 import socket #实力一个sk接口 sk = socket.socket() #socket()默认TCP协议 #绑定地址,(‘ip’,端口) sk.bind(('127.0.0.1',8899)) #监听链接 sk.listen() #接收客户端链接 ,conn建立好的链接,addr客户端地址 conn,addr = sk.accept() #接收消息 ret = conn.recv(1024) print(ret) #向客户端发送消息 conn.send(b'hello') #关闭客户端套接字 conn.close() #关闭服务端套接字 sk.close()
clien端
import socket sk = socket.socket() # 创建客户端sk sk.connect(('127.0.0.1',8899)) #去链接服务端(‘ip',端口) sk.send(b'ha,ha') #向服务端发送消息 ret = sk.recv(1024) #接收消息 print(ret) sk.close() #关闭
问题:重启服务端时可能会遇到
我们可能会遇到下面的问题:

解决方法:
#加入一条socket配置,重用ip和端口 import socket from socket import SOL_SOCKET,SO_REUSEADDR sk = socket.socket() sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加 sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字 sk.listen() #监听链接 conn,addr = sk.accept() #接受客户端链接 ret = conn.recv(1024) #接收客户端信息 print(ret) #打印客户端信息 conn.send(b'hi') #向客户端发送信息 conn.close() #关闭客户端套接字 sk.close() #关闭服务器套接字(可选)
TCP 时间戳服务器
创建 TCP 服务器
server端
它是一个 TCP 服务器程序,它接受客户端发送的数据 字符串,并将其打上时间戳(格式:[时间戳]数据)并返回给客户端(“server”代表时间戳 TCP 服务器,其他文件以类似的方式命名)。
服务端
from socket import * from time import ctime #导入了 time.ctime()和 socket 模块的所有属性。 host = '127.0.0.1' #本地回环地址 port = 9000 #端口 bufsiz = 1024 #将缓冲区大小设置为 1KB addr = (host, port) tcpsk = socket(AF_INET, SOCK_STREAM) tcpsk.bind(addr) #绑定地址 tcpsk.listen(5) #listen()方法的参数是在连接被转接或拒绝之前,传入连接请求的最大数。 while True: print('waiting for connection.....') Conn,Addr = tcpsk.accept() print('...connected from:',Addr) while True: data = Conn.recv(bufsiz).decode('utf-8') print(data) if not data: break data = '[%s] %s' % (ctime(), data) Conn.send(data.encode('utf-8') ) #ctime()当前格式化时间 Conn.close() tcpsk.close()
创建 TCP 客户端
clien端
这个脚本连接到服务器,并以逐行数据的形式提 示用户。服务器则返回加了时间戳的相同数据,这些数据最终会通过客户端代码呈现给 用户。
from socket import * host = '127.0.0.1' #本地回环地址 port = 9000 #端口 bufsiz = 1024 #将缓冲区大小设置为 1KB addr = (host, port) tcpck = socket(AF_INET,SOCK_STREAM) tcpck.connect(addr) while True: data = input('>').encode('utf-8') if not data: break tcpck.send(data) data = tcpck.recv(bufsiz).decode('utf-8') if not data: break print(data) tcpck.close()
基于UDP 协议的 socket
创建UDP服务器
UDP 服务器不需要 TCP 服务器那么多的设置,因为它们不是面向连接的。除了等待传 入的连接之外,几乎不需要做其他工作。
import socket import time #导入时间模块 HOST = '127.0.0.1' PORT = 9000 BUFSIZ = 1024 ADDR = (HOST,PORT)配置变量 udpsk = socket.socket(type = socket.SOCK_DGRAM) udpsk.bind(ADDR) #bind的调用与TCP相同 #不同之处在于这里没用“监听传入的连接”,因为UDP是无连接的 while True: print('message..') data,addr = udpsk.recvfrom(BUFSIZ) msg = data.decode('utf-8') T = '[%s] %s' % (time.ctime(),msg) udpsk.sendto(T.encode('utf-8'),addr) print(':',addr) udpsk.close()
UDP时间戳客户端,它提示用户输入发送给服务器的消息,并接收消息,并接收服务器加了时间戳前缀的消息,然后显示给用户。
import socket HOST = '127.0.0.1' PORT = 9000 BUFSIZ = 1024 ADDR = (HOST,PORT)#配置变量 udpck = socket.socket(type=socket.SOCK_DGRAM)#udp协议的socket() while True: data = input('>').encode('utf-8') if not data: break udpck.sendto(data, ADDR) mag,ADDR = udpck.recvfrom(BUFSIZ) l = mag.decode('utf-8') if not data: break print(l,ADDR) udpck.close()

浙公网安备 33010602011771号