ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

网络编程(二)

2022-04-15 19:00:50  阅读:159  来源: 互联网

标签:socket 编程 sock 网络 client recv 服务端 客户端


网络编程(二)

socket套接字简介

# socket套接字是一门技术
	socket套接字可以帮我们实现C/S架构的程序两端交互
    socket套接字可以通过python内置的socket模块快速实现OSI七层操作
    """
    以后我们写软件连socket的影子都看不到 因为被封装起来
    socket是最底层的原理 很多框架都封装了 其实我们不需要深入研究
    """

socket模块

# 编程思想
	对于C/S架构的程序,无论编写还是运行,都要遵循:
        '优先考虑服务端,有了服务才能有客户'
# 服务端代码
	import socket

    server = socket.socket()  # 获取连接对象
    server.bind(('127.0.0.1',8080))  # 给连接对象绑定地址
    server.listen(5)  # 允许最大排队数  这个数加上正在连接数就是最大连接数
    sock, addr = server.accept()  # 阻塞程序,没有获取到连接的客户端会阻塞程序运行
    print(addr)
    while True:  # 循环通信
        data = sock.recv(1024)  # 从连接里获取客户端的数据
        print(data.decode('utf8'))
        msg = input('>').strip()
        sock.send(msg.encode('utf8'))  # 通过连接把数据发给客户端
    sock.close()  # 关闭与客户端连接
    server.close()  # 关闭连接对象
    
# 客户端代码
	import socket

    client = socket.socket()  # 获取连接对象
    client.connect(('127.0.0.1',8080))  # 绑定连接服务端的地址
    while True:  # 循环通信
        msg = input('>').strip()
        client.send(msg.encode('utf8'))  # 发数据到服务端
        data = client.recv(1024)  # 获取服务端发来的数据
        print(data.decode('utf8'))
    client.close() # 关闭连接
    
###########################
服务端与客户端首次交互
	一边是recv那么另一边必须是send  两边不能相同 否则就'冷战'了
###########################

通信循环

# 思路
	1.所有通信消息要用户事实输入
    	利用input获取用户输入信息
    2.接收一次消息之后不能结束程序,应当获取输入,返回消息,然后等待下一次接发消息
    	利用While循环实现
# 代码编写
	详见上段代码

代码优化及链接循环

1.不能发空消息
	搞个if判断len(用户输入即可)
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判断
  """
  客户端如果异常断开 服务端代码应该重新回到accept等待新的客人

# 目前我们的服务端只能实现一次服务一个人 不能做到同事服务多个 学了并发才可以实现

半连接池

listen(5)
# py文件默认同一时间只能运行一次 如果想单独分开运行多次

# 半连接池
	设置的最大等待人数  >>>:  节省资源 提高效率

黏包问题

# 客户端
data1 ='aaa'
data2 ='aaa'
data3 ='aaa'
client.send(data1.encode('utf8'))
client.send(data2.encode('utf8'))
client.send(data3.encode('utf8'))

# 服务端
data1 = sock.recv(1024)
print(data1)
data2 = sock.recv(1024)
print(data2)
data3 = sock.recv(1024)
print(data3)

# 客户端输出
b'aaaaaaaaa'
b''
b''

为什么发了三次数据,结果全都在第一次数据里?
"""
# TCP协议的特点
	会将数据量比较小并且时间间隔比较短的数据整合到一起发送
  并且还会受制于recv括号内的数字大小(核心问题!!!)
  流式协议:跟水流一样不间断
    
"""
"""
问题产生的原因其实是因为recv括号内我们不知道即将要接收的数据到底多大
如果每次接收的数据我们都能够精确的知道它的大小 那么肯定不会出现黏包
"""
eg:
    data1 = sock.recv(3)
    print(data1)
    data2 = sock.recv(3)
    print(data2)
    data3 = sock.recv(3)
    print(data3)
    # 客户端输出
    b'aaa'
    b'aaa'
    b'aaa'

解决黏包问题

解决思路:
    我们可以发送固定大小的数据,客户端接收就不会出现黏包
    
# struct模块
	import struct

    data1 = 'Hello world!'
    data2 = 'afdkjhfdafklajflkhaslfjahfjkahflksafjl'
    print(len(data1), len(data2))  # 12 38
    ret1 = struct.pack('i', len(data1))
    ret2 = struct.pack('i', len(data2))
    print(len(ret1), len(ret2))  # 4 4
    res1 = struct.unpack('i',ret1)
    res2 = struct.unpack('i',ret2)
    print(res1, res2)  # (12,) (38,)
    
# 具体解决黏包思路
	1.先将用struct模块打包成固定长度
    2.把打包后的长度发过去
    3.对方用unpack解析获取真实长度
    4.根据真实长度用recv(真实长度)接收数据

代码演示

1.编写一个cs架构的软件
	就两个功能
  	一个视频下载:从服务端下载视频
    一个视频上传:从客户端上传视频
 	"""
 	只要实现就可以 无需整合(如果能做到更好)
 	"""
# 代码
	服务端
    import socket

    # 获取连接对象
    import struct

    server_packer = socket.socket()
    server_packer.bind(('127.0.0.1',8081))
    server_packer.listen(1)
    sock,addr = server_packer.accept()
    # 读取视频文件
    with open('1.mp4','rb') as f:
        data = f.read()
    # 打包
    ret = struct.pack('i', len(data))
    # 发送打包后的数据
    sock.send(ret)
    # 发送真实数据
    sock.send(data)
    sock.close()
    server_packer.close()
    
    客户端
    import struct
    import socket

    # 获取连接对象
    client = socket.socket()
    client.connect(('127.0.0.1',8081))
    # 获取打包后长度并解析
    ret = client.recv(4)
    res = struct.unpack('i',ret)
    # 根据解析的长度获取真实数据
    data = client.recv(res[0])
    # 写入文件
    with open('2.mp4','wb') as f:
        f.write(data)
    client.close()
    

标签:socket,编程,sock,网络,client,recv,服务端,客户端
来源: https://www.cnblogs.com/cxysbyh/p/16150577.html

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

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

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

ICode9版权所有