python socket 编程简单入门
想讲讲套接字的概念
套接字,即英文socket的中文意译,起源于20世纪70年代,是加利福利亚大学的伯克利版本UNIX(称为BSD UNIX)的一部分。目的是实现主机上运行的一个程序与另一个运行的程序进行通信。
套接字像一个电话插孔--允许通信的一些基础设施,那么主机号和端口号就像区号和电话号码的组合。
套接字类型
1 UNIX套接字
即AF_UNIX, 它代表地址家族:UNIX。Python在内的大多数受欢迎的平台都使用缩写AF指代。
2 网络套接字
即AF_INET,它代表地址家族:因特网。而AF_INET6用于IPV6
3 其他套接字
AF_NETLINK家族,AF_TIPC ,这两种是特殊的LINUX套接字类型
python支持以上四种套接字
实际使用中,我们用的最多的时AF_INET,其有可以分为:
1 面向连接的套接字
即实现TCP协议的套接字,具体名称为SOCK_STREAM
2 无连接的套接字
即实现UDP协议的套接字,名称为SOCK_DGRAM(datagram数据报)
接下就是Python 如何进行socket编程的介绍。
python通过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例子:
SimpleSocketServer.py
实现了一个最多同时处理5个socket client 的简单socket server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #coding:'utf-8' import socket import threading import sys BUFSIZE = 1024 class SimpleSocketServer(): def __init__( self , ip, port): self .ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self .addr = (ip, port) self .stop = False def start( self ): self .ss.bind( self .addr) self .ss.listen( 5 ) try : while True : if self .stop: break cs, addr = self .ss.accept() th_cs = threading.Thread(target = self .cs_handler, args = (cs, addr)) th_cs.start() except KeyboardInterrupt: self .ss.close() sys.exit() def stop_server( self ): self .stop = True def cs_handler( self , cs, addr): print 'client[%s] has client to server...' % str (addr) try : while True : data = cs.recv(BUFSIZE) if not data: break cs.send( 'hello, you send data is [%s]' % data) except KeyboardInterrupt: sys.exit() if __name__ = = '__main__' : SimpleSocketServer( '127.0.0.1' , 33233 ).start() |
SimpleSocketClient.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #coding:'utf-8' import socket import thread import sys if __name__ = = '__main__' : cs = socket.socket(socket.AF_INET,socket.SOCK_STREAM) cs.connect(( '127.0.0.1' , 33233 )) while True : try : INPUT = raw_input ( 'you input >' ) cs.send( INPUT ) data = cs.recv( 1024 ) print 'from server: %s' % data except KeyboardInterrupt: cs.close() sys.exit( 0 ) break except EOFError: print 'Unknown End of file!' continue |
特别说明:
当超过一个以上的client连到socket server时,在终端会看到
λ python SimpleSocketServer.py
client[('127.0.0.1', 49308)] has client to server...
client[('127.0.0.1', 49568)] has client to server...
这是为什么呢?
一旦TCP服务器接受了一个连接,就会返回(accept()实现)一个独立的客户端套接字,用来与即将到来的消息进行交互。这时原始服务器套接字就能继续接受新的客户端连接请求了。
下面是一个UDP的例子:
udp服务器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #coding:'utf-8' import socket import threading import sys BUFSIZE = 1024 class SimpleUDPServer(): def __init__( self , ip, port): self .ss = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self .addr = (ip, port) self .stop = False def start( self ): self .ss.bind( self .addr) try : while True : if self .stop: break data, addr = self .ss.recvfrom(BUFSIZE) print 'udp server recvfrom client[%s]:%s ' % ( str (addr), data) self .ss.sendto( 'hello, you send data is [%s]' % data, addr) except KeyboardInterrupt: self .ss.close() sys.exit() def stop_server( self ): self .stop = True if __name__ = = '__main__' : SimpleUDPServer( '127.0.0.1' , 33233 ).start() |
udp客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #coding:'utf-8' import socket import thread import sys if __name__ = = '__main__' : cs = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) addr = ( '127.0.0.1' , 33233 ) while True : try : INPUT = raw_input ( 'you input >' ) cs.sendto( INPUT , addr) data, addr = cs.recvfrom( 1024 ) print 'from server[%s]: %s' % ( str (addr),data) except KeyboardInterrupt: cs.close() sys.exit( 0 ) break except EOFError: print 'Unknown End of file!' continue |
当udp有接受到client连接到的数据时:
λ python SimpleUDPServer.py
udp server recvfrom client[('127.0.0.1', 57959)]:;;
udp server recvfrom client[('127.0.0.1', 57959)]:ffdfdf
udp server recvfrom client[('127.0.0.1', 63667)]: 111
udp server recvfrom client[('127.0.0.1', 63667)]:fdfdf
UDP和TCP服务器之间的另一个显著 差异是,因为数据报套接字是无连接的,所以就没有为了成功通信而使一个客户端连接到一个独立的套接字“转换”的操作
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署