ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

socket套接字

2022-04-15 21:32:22  阅读:152  来源: 互联网

标签:socket send server print client msg 接字


目录

socket套接字简介

# 需求:编写cs架构的程序 实现数据交互
	需要编写OSO七层相当复杂,但是由于OSI七层是所有cs架构程序都需要经历的过程,所以由固定的模块
    socket模块:提供了快捷方式不需要自己处理每一层
'''
我们写软件,是看不到socket的,因为都被封装了起来
socket是最低层的原理,很多框架都被封装,不需要深入研究
'''

socket模块

cs架构的软件无论实在编写还是运行,都应该先考虑服务端
# 服务端
import socket

server = socket.socket()
"""
通过查看源码得知 
括号内不写参数默认就是基于网络的遵循TCP协议的套接字
"""

server.bind(('127.0.0.1', 8008))
"""
服务端应该具备的特征
    固定的地址
127.0.0.1是计算机的本地回环地址 只有当前计算机本身可以访问
"""
server.listen(3)
'''半连接池:可以决定客户端的等待人数'''
sock, addr = server.accept()
"""
listen和accept对应TCP三次握手服务端的两个状态
"""
print(addr)
msg = sock.recv(1024)
print(msg.decode('utf8'))
sock.send('hello client'.encode('utf8'))
sock.close()
server.close()

#  客户端
import socket

client = socket.socket()
client.connect(('127.0.0.1',8008))
client.send('hello world'.encode('utf8'))
msg = client.recv(1024)
print(msg.decode('utf8'))
client.close()
'''
服务端与客户端的recv与send必须错开,不能同时存在,否则两边,都等待消息或者发送消息,程序阻塞
'''

通信循环

1.解决消息固定的问题
	利用input获取用户输入
2.解决通信循环问题
# 服务端
import socket

server = socket.socket()
server.bind(('127.0.0.1', 8008))
server.listen(3)
clint, addr = server.accept()
while True:
    msg = clint.recv(1024)
    print(msg.decode('utf8'))
    msg_send = input('请输入信息:')
    clint.send(msg_send.encode('utf8'))
clint.close()
server.close()

# 客户端
import socket

client = socket.socket()
client.connect(('127.0.0.1',8008))
while True:
    msg_send = input('请输入信息:')
    client.send(msg_send.encode('utf8'))
    msg = client.recv(1024)
    print(msg.decode('utf8'))
client.close()



代码优化及链接循环

1.发送消息不能为空
	统计长度并判断
2.反复重启之后服务端可能会报错:address in use
这个错误在苹果电脑报的比较频繁  windows频率较少
from socket import SOL_SOCKET,SO_REUSEADDR
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)  # 加在bind前
3.链接循环
'''
如果是windows 客户端异常退出之后服务端会直接报错
	处理方式:异常处理
如果是mac或者linux服务端会接收到一个空消息
	处理方式:len判断
'''
# 服务端
import socket
from socket import SOL_SOCKET,SO_REUSEADDR



server = socket.socket()
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
server.bind(('127.0.0.1', 8008))
server.listen(3)
clint, addr = server.accept()
while True:
    try:
        msg = clint.recv(1024)
        print(msg.decode('utf8'))
        msg_send = input('请输入信息:')
        if len(msg_send) == 0:
            continue
        clint.send(msg_send.encode('utf8'))
    except Exception as f:
        print('客户端断开链接')
        break
clint.close()
server.close()

# 客户端
import socket

client = socket.socket()
client.connect(('127.0.0.1',8008))
while True:
    msg_send = input('请输入信息:')
    if len(msg_send) == 0:
        continue
    client.send(msg_send.encode('utf8'))
    msg = client.recv(1024)
    print(msg.decode('utf8'))
client.close()


客户端如果异常断开 服务端代码应该重新回到accept等待新的客人
# 当前服务端只能实现一次服务一个人,不能同时服务多个,学习并发之后可以实现

半连接池

listen(5)
# 在py文件默认同一时间只能运行一次,如果想单独分开运行多次 就需要用半连接池
# 半连接池
	设置的最大等待人数:节省资源 提高效率

黏包问题

data1 = conn.recv(1024)
print(data1)
data2 = conn.recv(1024)
print(data2)
data3 = conn.recv(1024)
print(data3)

client.send(b'hello')
client.send(b'jason')
client.send(b'kevin')
'''
三次打印店的结果
b'hellojasonkevin'
b''
b''
'''
# TCP协议特点
会将数据量比较小并且时间间隔比较短的数据整合到一起发送
并且还会受限制与recv括号内数字的大小(核心问题)
流式协议:跟水流一样不间断
'''
 问题产生的原因其实是因为recv括号内我们不知道将要接受的数据到底多大
 如果每次接收的数据我们都能够精确的知道他的大小 那么肯定不会出现黏包
'''
思路:
	核心问题是不知道即将接收的数据多大
    如果能够精准的知道数据量多大 那么黏包问题就自动解决了
    

黏包问题的解决

# struct模块
import struct
msg = 'hello world'
print(len(msg))  # 11
res = struct.pack('i',len(msg)) #第一个参数是格式
print(len(res))  # 4
res1 = struct.unpack('i',res)
print(len(res1))  # (11,) 

data2 = 'hello baby baby baby baby baby baby baby baby'
  print(len(data2))  # 45
  res2 = struct.pack('i', len(data2))
  print(len(res2))  # 4
  ret2 = struct.unpack('i', res2)
  print(ret2)  # (45,)
    
'''
pack可以将任意长度的数据打包成固定长度
unpack可以将固定长度的数据解包成打包之前的长度

解决黏包问题思路:
	1.将真是数据打包成固定长度的包
	2.将福哦顶长度的包先发给对方
	3.对方接收到包之后进行解包获取真实数据长度
	4.接收真实数据长度
'''

标签:socket,send,server,print,client,msg,接字
来源: https://www.cnblogs.com/mzzxlz/p/16151015.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有