网络编程之socket
什么是socket?
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实即使一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部。让Socket去组织数据,以符合指定的协议。
通过代码简单看一下socket:
import socket #创建一个socket对象 server = socket.socket() #相当于创建了一部电话 ip_port = ('192.168.111.1',8001) #创建一个电话卡 server.bind(ip_port) #插上电话卡 server.listen(5) #监听着电话,我能监听5个,接到一个电话之后,后面还能有四个人给我打电话,但是后面这四个人都要排队等着,等着我第一个电话挂掉,再来第6个的时候,第六个人的手机会报错 print('11111') #等着别人给我打电话,打来电话的时候,我就拿到了和对方的这个连线通道conn和对方的电话号码addr conn,addr = server.accept() #阻塞住,一直等到有人连接我,连接之后得到一个元祖,里面是连线通道conn和对方的地址(ip+端口) print('22222') print(conn) print('>>>>>>>>>',addr) while True: from_client_data = conn.recv(1024) #服务端必须通过两者之间的连接通道来收消息 from_client_data = from_client_data.decode('utf-8') print(from_client_data) if from_client_data == 'bye': break server_input = input('明威说>>>>:') conn.send(server_input.encode('utf-8')) if server_input == 'bye': break conn.close() #挂电话 server.close() #关手机 test_server.py
listen(3),这个3的意思是我连接着一个,后面还可以有三个排队的,也就是支持4个人的服务,但是后面三个要排队。
#_*_coding:utf-8_*_ import socket import time client = socket.socket() server_ip_port = ('192.168.111.1',8001) client.connect(server_ip_port) while True: client_input = input('小文说>>>>:') client.send(client_input.encode('utf-8')) #给服务端发送消息 if client_input == 'bye': break from_server_data = client.recv(1024) print('来自服务端的消息:',from_server_data.decode('utf-8')) if from_server_data.decode('utf-8') == 'bye': break client.close() #客户端挂电话 test_client.py
注意:先运行server,然后再运行client,然后你会发现client这个文件再输出台的地方让你输入内容,你输入一个内容然后回车,你会发现server那边的控制台就输出了以client发送的内容
TCP协议下的socket:
先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束
上代码感受一下,需要创建两个文件,文件名称随便起,为了方便看,我的两个文件名称为tcp_server.py(服务端)和tcp_client.py(客户端),将下面的server端的代码拷贝到tcp_server.py文件中,将下面client端的代码拷贝到tcp_client.py的文件中,然后先运行tcp_server.py文件中的代码,再运行tcp_client.py文件中的代码,然后在pycharm下面的输出窗口看一下效果。
server端代码示例(如果比喻成打电话)
import socket sk = socket.socket() 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_server.py
client端代码示例
import socket sk = socket.socket() # 创建客户套接字 sk.connect(('127.0.0.1',8898)) # 尝试连接服务器 sk.send(b'hello!') ret = sk.recv(1024) # 对话(发送/接收) print(ret) sk.close() # 关闭客户套接字 tcp_client.py
ocket绑定IP和端口时可能出现下面的问题:
#加入一条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() #关闭服务器套接字(可选) 解决办法
但是如果你加上了上面的代码之后还是出现这个问题:OSError: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。那么只能换端口了,因为你的电脑不支持端口重用。
记住一点,用socket进行通信,必须是一收一发对应好。