Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口
服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束
accept 是一个阻塞函数 会一直等到有客户端链接过来 在继续执行 connect本质实在进行三次握手 也是一个数据传输的过程 如果服务器没有立马响应 也会阻塞
send
发送数据 本质上是把数据交给操作系统来进行发送 一旦数据交给了操作系统 后续的发送
应用程序就无法控制了 ,send一般不会卡 当然 如果数据量很大就会阻塞 scoket套接字是从操作系统缓存区读取数据 如果当前还没有任何数据, 就会进入阻塞会一直等到有数据到来 再继续执行send与recv对应,不要出现两边都是相同的情况
异常 # 如果已经开启了服务器 再次运行将会抛出 端口占用异常 把之前开启的服务器关掉即可 1.可能是由于你已经启动了服务器程序,却又再次启动了服务器程序,同一个端口不能被多个进程使用导致! 2.三次握手或四次挥手时,发生了异常导致对方程序已经结束而服务器任然处于time_wait状态导致! 3.在高并发的场景下,由于链接的客户端太多,也会产生大量处于time_wait状态的链接
升级版
import socket # 产生对象 server = socket.socket() # 绑定ip和端口 server.bind(('127.0.0.1',8080)) # 监听 server.listen(5) while True: # 接收 conn,addr = server.accept() # print(conn) # print(addr) # 接收 while True: try: data = conn.recv(1024) print(data) # 防止客户端发生异常或断掉 if len(data) == 0: break conn.send(data.upper()) except ConnectionResetError as a: print(a) break conn.close() 服务端 import socket # 产生对象 client = socket.socket() # 绑定 client.connect(('127.0.0.1',8080)) while True: # 输入的信息为字符串类型,传输数据是由二进制数据传送的 msg = input('>>>..').encode('utf-8') # 防止输入的信息为空 if len(msg) == 0: continue client.send(msg) data = client.recv(1024) print(data) 客户端代码
import socket server = socket.socket() server.bind(('127.0.0.1',8080)) server.listen(5) conn ,addr = server.accept() data = conn.recv(1024) print(data) data = conn.recv(10) print(data) data = conn.recv(7) print(data) data = conn.recv(20) print(data) 服务器 import socket client = socket.socket() client.connect(('127.0.0.1',8080)) client.send(b'strawberry') client.send(b'berries') client.send(b'interconnection') 客户端 # TCP特点# 会将数据量比较小的并且时间间隔比较短的数据# 不知到对方要传的数据有多大# 将数剧打包成固定长度 发送给对方例子:
import socket import subprocess server = socket.socket() server.bind(('127.0.0.1',8080)) server.listen(5) # 敲入命令行拟cmd实行命令 while True: conn,addr = server.accept() while True: try: cmd = conn.recv(1024) if not len(cmd): break cmd = cmd.decode('utf-8') obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) res = obj.stdout.read() + obj.stderr.read() print(len(res)) conn.send(res) except ConnectionResetError as a: print(a) break conn.close() 服务端 import socket client = socket.socket() client.connect(('127.0.0.1',8080)) while True: cmd = input('>>>').encode('utf-8') if not len(cmd): continue client.send(cmd) data = client.recv(1024) print(data.decode('gbk')) 客户端解决粘包问题 服务端 1.先制作一个发送给客户端的字典 2.制作字典的报头 3.发送字典的报头 4.发送字典 5.再发真实数据 客户端 1.先接受字典的报头 2.解析拿到字典的数据长度 3.接受字典 4.从字典中获取真实数据的长度 5.接受真实数据
如:
import socket import struct import json import subprocess server = socket.socket() server.bind(('127.0.0.1',8080)) server.listen(5) while True: conn,addr = server.accept() while True: try: cmd = conn.recv(1024) if not len(cmd): break cmd = cmd.decode('utf-8') obj = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) res = obj.stdout.read() + obj.stderr.read() # 一个文件的报头 d = {'name':'baobo','file_size':len(res),'info':'asdfghjwertyuwertzxcvbnmdfghjkejhk'} json_d = json.dumps(d) # 1.先制作一个字典的报头 header = struct.pack('i',len(json_d)) # 2.发送报头长度 conn.send(header) # 3.发送字典 conn.send(json_d.encode('utf-8')) # 4.在发送真实数据 conn.send(res) except ConnectionResetError as a: print(a) break conn.close() 服务端import socket import struct import json client = socket.socket() client.connect(('127.0.0.1',8080)) while True: cmd = input('>>>').encode('utf-8') if not len(cmd): continue client.send(cmd) # 1.先接受字典报头 header_dict = client.recv(4) # 2.解析报头 获取字典的长度 dict_size = struct.unpack('i',header_dict)[0] # 3.接收字典数据 dict_bytes = client.recv(dict_size) dict_json = json.loads(dict_bytes.decode('utf-8')) # 4.从字典中获取信息 print(dict_json) recv_size = 0 real_data = b'' while recv_size < dict_json.get('file_size'): data = client.recv(1024) real_data += data recv_size += len(data) print(real_data.decode('gbk')) 客户端
转载于:https://www.cnblogs.com/komorebi/p/11318329.html
相关资源:JAVA上百实例源码以及开源项目