socket又称为套接字,它是所有网络通信的基础。网络通信其实就是进程间的通信,socket主要使用IP地址、协议、端口号来标识一个进程。端口号的范围为0~65535(用户端口号一般大于1024),协议有很多种,一般我们经常用到的就是TCP、UDP。
15.1 socket常用函数
socket.socket(socket_family,socket_type,protocol=0) 创建套接字
socket_family可以是如下参数:
socket.AF_INET: 使用IPv4协议。
socket.AF_INET6:使用IPv6协议。
socket.AF_UNIX: 只能够用于单一的Unix系统进程间通信。
socket_type可以是如下参数:
socket.SOCK_STREAM:流式socket , for TCP
socket.SOCK_DGRAM: 数据报式socket , for UDP
socket.SOCK_RAW:原始套接字。普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
socket.SOCK_RDM: 一种可靠的UDP形式,即保证交付数据报但不保证顺序。
socket.SOCK_SEQPACKET: 可靠的连续数据包服务。
protocol参数:0(默认)与特定的地址家族相关的协议。如果是0,则系统就会根据地址格式和套接类别,自动选择一个合适的协议。
服务器端套接字函数如下:
bind()
listen(backlog)
accept()
客户端socket函数如下:
connect(address)
connect_ex(address)
服务器端和客户端公共socket函数如下:
settimeout(timeout)
gettimeout()
recv(bufsize[,flag])
send(string[,flag])
sendall(string[,flag])
sendto(string[,flag],address)
recvfrom(bufsize[.flag])
close()
setsockopt(level,optname,value)
例:setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 防止socket server重启后端口被占用。
getsockopt(level,optname[.buflen])
setblocking(flag)
getpeername()
getsockname()
15.2 创建TCP服务器端和客户端实例
TCP服务器端代码实例如下:
import socket
import threading
import time
import sys
def tcp_server():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 防止socket server重启后端口被占用(socket.error: [Errno 98] Address already in use)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('127.0.0.1', 6666))
s.listen(10)
except socket.error as msg:
print(msg)
sys.exit(1)
print('Waiting connection...')
while 1:
conn, addr = s.accept()
t = threading.Thread(target=deal_data, args=(conn, addr))
t.start()
def deal_data(conn, addr):
print('Accept new connection from {0}'.format(addr))
conn.send(('Hi, Welcome to the server!').encode())
while 1:
data = conn.recv(1024)
print('{0} client send data is {1}'.format(addr, data.decode()))
if data.decode() == 'exit' or not data:
print('{0} connection close'.format(addr))
conn.send(bytes('Connection closed!', 'UTF-8'))
break
conn.send(bytes('Hello, {0}'.format(data), "UTF-8")) # a bytes-like object is required, not 'str'
conn.close()
if __name__ == '__main__':
tcp_server()
TCP客户端代码实例如下:
import socket
import sys
def tcp_client():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 6666))
except socket.error as msg:
print(msg)
sys.exit(1)
print(s.recv(1024)) # 目的在于接受:Accept new connection from (...
while 1:
data = input('please input work: ').encode()
print(data)
s.send(data)
print('aa', s.recv(1024))
if data.decode() == 'exit':
break
s.close()
if __name__ == '__main__':
tcp_client()