基于socket简易版客户端,服务端交互

简易版客户端服务端交互

常识

AF_UNIX 是基于文件类型的套接字家族
AF_INET是 基础网络类型的套接字家族
socket 模块属性很多,可以直接使用from module import *语句 ,这样socket所有的数据都被带劲命名空间里了. 减少代码量(少用)

服务端

#1导入
import socket
# 2.获取套接字
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#3绑定
s.bind(('127.0.0.1',8070))
#4开机,监听
s.listen(1)
#5创建一个通道和地址,等待接受电话

conn,addr=s.accept()
#6接受这个值
data=conn.recv(1024)
#7释放数据
print(data)
#8用通道发送数据
conn.send('帅逼'.encode('gbk'))
#9关闭通道
conn.close()
#10关闭服务端
s.close()
             

客户端

#导入
import socket
#创建对象
s=socket.socket()
#连接服务端地址
s.connect(('127.0.0.1',8070))
s.send(b'adas')
#接受字节数据
data=s.recv(1024)
#打印展现出来
print(data.decode('gbk'))
#关闭
s.close()

 

基础知识混淆点


把b格式转成字符串
ss=str(b'hello',encoding='utf8')
等于这个
ss=b'hello'.decode('utf8')

把字符串转成b格式
by=bytes('hello',encoding='utf8')
by='hello'.encode('utf8')

解决客户端突然断开连接

客户端需要发信息一直发信息 所以有while循环 ,但是我们的服务端也需要一直接受信息,否则发信息就没有意义了

  • 但是 如果说客户端突然断开连接这个时候就会出现一下错误

    1567775794109

这个时候就需要加上try 以及 except EXCEPTION 如果出现了错误 ,那么咱们需要怎么做。。

总结

服务端server

#1导入
import socket
# 2.创建对象
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#3绑定
s.bind(('127.0.0.1',8070))
#开机,监听
s.listen(1)
#创建一个通道和地址,等待接受电话
conn,addr=s.accept()
#接受这个值
while True:
    try:
        #等待接受  最大收1024字节
        data=conn.recv(1024)
    #释放数据
        print(data.decode('utf8'))
    except Exception:
        conn.close()
        break

client 客户端

导入 创建 连接 发送信息 转换格式

import socket
#创建新对象
s=socket.socket()
#连接直接用
s.connect('127.0.0.1',8070)
#发送信息
while True:
	msg=input('输入')
    #发送输入数据
    s.send(msg.encode('utf8'))    
    

套接字加上连接循环通讯循环

服务端要一直稳定的运行,不能客户端断了 咱们的服务端等着连接的代码需要重写一遍,所以应该让服务端循环等着客户端的连接(但是接受,打印客户数据信息,需要在连接之后写)所以需要加上一个循环嵌套,循环嵌套是 内层嵌套运行break掉才会继续运行外层循环的信息(称之为结算运行)。

需求精简:服务端要能够一直的循环等待客户端连接,蛋不需要发一次信息就连接一次。

实现精简:嵌套循环 等待客户端连接代码写在大循环,接受客户数据信息,与打印信息放在内层循环里面。

……
#接受这个值
while True:
    print('等待客户端的连接')
    conn,addr=s.accept()
    while True:
        try:
            #等待接受  最大收1024字节
            data=conn.recv(1024)
        #释放数据
            print(data.decode('utf8'))
        except Exception:
            conn.close()
            break
    conn.close()

addr是客户端的地址

解决粘包问题

基础概念

TCP粘包就是指发送方发送的若干个包数据 --->接收方接受时粘成一个包,两个数据包是有数据头尾的,后一个包可能会紧接着前一个包的尾

可能是发送方造成的,也可能是有接收方造成的,发送方因其粘包是有TCP协议本身造成的,如果连续几次发送数据很少,那么TCP会根据优化算法把这些数据合成一个包后一次发送出去,这样接收方就收到了粘包数据。

解决方案

长度不变,就不会粘包,因为粘包,发送方或者接收方可能会少数据多数据,固定他的字节的长度就不会产生粘包

struct模块

为字节流加上自定义固定长度报头,报头中包含字节流长度,然后一次send到对端,对端在接收时,先从换从中取出定长的报头,然后打开包裹取真实数据,

主要是把一个类型转成固定长度的bytes。核心

步骤

导包-->打包Pack('模式',数据)--解包

# 导报#
import struct
#打包创建对象里面有模式(以字符串表示),跟这个数据对象
obj=struct.pack('i',1234532111)
print(obj)
print(len(obj))  #固定4个字节的长度
#打开包裹,反解出来
l=struct.unpack('i',obj)[0]#是一个小元祖 取索引第0个
print(l)

posted @ 2019-09-10 22:56  Huise.J  阅读(206)  评论(0编辑  收藏  举报