1. socket 编程概念
socket本质上就是在2台网络互通的电脑之间,架设一个通道,两台电脑通过这个通道来实现数据的互相传递。网络通信都是基于ip+port定位到目标机器上的具体服务,操作系统有0-65535个端口,每个端口都可以独立对外提供服务。
建立一个socket必须至少有2端, 一个服务端,一个客户端, 服务端被动等待并接收请求,客户端主动发起请求, 连接建立之后,双方可以互发数据。
2. socket 类型
socket.SOCK_STREAM # tcp 协议
socket.SOCK_DGRAM # udp 协议
socket.SOCK_RAW #原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
socket.SOCK_RDM #是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM #通常仅限于高级用户或管理员运行的程序使用。
3. Socket Families(地址簇)
socket.AF_UNIX # unix本机进程间通信
socket.AF_INET # IPV4
socket.AF_INET6 # IPV6
4. socket 方法
s = socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None) #生成socket对象
s.bind(address) #将套接字绑定到地址。address地址的格式取决于地址簇。在AF_INET下,以元组(host,port)的形式表示地址。
s.setblocking(bool) #是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。
s.connect(address) #连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
s.close() #关闭套接字
s.recvfrom(bufsize[.flag]) # 与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。
s.sendall(string[,flag]) #将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。内部通过递归调用send,将所有内容发送出去。
s.sendto(string[,flag],address) #将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。
s.getpeername() #返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。
s.fileno() #套接字的文件描述符
5. Socket Server
import socket
tcpsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
tcpsocket.bind(('127.0.0.1',8080))
tcpsocket.listen(5)
while True:
conn,client_addr = tcpsocket.accept()
print('客户端',client_addr)
while True:
try:
msg = conn.recv(1024)
print(msg.decode('utf-8'))
conn.send('sb'.encode('utf-8'))
except Exception:
break
conn.close()
tcpsocket.close()
6. Socket Client
import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('127.0.0.1',8080))
# s.connect(('0,0,0,0',8080))
while True:
try:
cmd = input('cmd>>: ').strip()
if not cmd:continue
s.send(cmd.encode('utf-8'))
res = s.recv(1024)
print('serves_res',res.decode('utf-8'))
except Exception:
break
s.close()
7. udp协议下的socket
Server端:
import socket
ip_port = ('127.0.0.1',9000)
BUFSIZE = 1024
udp_server_client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udp_server_client.bind(ip_port)
while True:
msg,addr = udp_server_client.recvfrom(BUFSIZE)
print('recv',msg,addr)
udp_server_client.sendto(msg.upper(),addr)
Client端:
import socket
ip_port = ('127.0.0.1',9000)
BUFSIZE = 1024
udp_server_client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
msg = input('>>: ').strip()
# if not msg:continue
udp_server_client.sendto(msg.encode('utf-8'),ip_port)
back_msg,addr = udp_server_client.recvfrom(BUFSIZE)
print(back_msg.decode('utf-8'))