Tall version of the package to solve the sticky problem

recv works

Verify the server buffers the data does not take complete, execution and implementation of recv, recv will continue to value.

Server : go this way according to two two

import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8080))
phone.listen(5)
conn,client_addr = phone.accept()
from_client_data1 = conn.recv(2)
print(from_client_data1)
from_client_data2 = conn.recv(2)
print(from_client_data2)
from_client_data3 = conn.recv(1)
print(from_client_data3)
conn.close()
phone.close()
'''
b'he'
b'll'
b'o'

'''

client

import socket
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8080))
phone.send('hello'.encode('utf-8'))
phone.close()
The authentication server to take over the buffer, and the recv operation performed, then the client 20 seconds off premise, the blocked recv

serve

import socket
phone =socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8080))
phone.listen(5)
conn, client_addr = phone.accept()
from_client_data = conn.recv(1024)
print(from_client_data)
print(111)
conn.recv(1024) # 此时程序阻塞20秒左右,因为缓冲区的数据取完了,并且20秒内,客户端没有关闭。
print(222)

conn.close()
phone.close()
'''
b'hello'
111
222
'''

client

import socket
import time
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8080))
phone.send('hello'.encode('utf-8'))
time.sleep(20)
Buffer authentication server to take over, and the recv performed, then the client is closed, will be taken to the empty string recv

server

import socket
phone =socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8080))
phone.listen(5)
conn, client_addr = phone.accept()
from_client_data1 = conn.recv(1024)
print(from_client_data1)
from_client_data2 = conn.recv(1024)
print(from_client_data2)
from_client_data3 = conn.recv(1024)
print(from_client_data3)
conn.close()
phone.close()

'''
b'hello'
b''
b''
'''

client

import socket
import time
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8080))
phone.send('hello'.encode('utf-8'))
phone.close()

Tall version of the package to solve the sticky problem

1. 高大上版: 自定制报头

dic = {'filename': XX, 'md5': 654654676576776, 'total_size': 26743}

2. 高大上版:可以解决文件过大的问题.

server

import socket
import subprocess
import struct
import json
phone = socket.socket()

phone.bind(('127.0.0.1',8848))

phone.listen(2)
# listen: 2 允许有两个客户端加到半链接池,超过两个则会报错

while 1:
    conn,addr = phone.accept()  # 等待客户端链接我,阻塞状态中
    # print(f'链接来了: {conn,addr}')

    while 1:
        try:

            from_client_data = conn.recv(1024)  # 接收命令


            if from_client_data.upper() == b'Q':
                print('客户端正常退出聊天了')
                break

            obj = subprocess.Popen(from_client_data.decode('utf-8'),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE,

                                   )
            result = obj.stdout.read() + obj.stderr.read()
            total_size = len(result)

            # 1. 自定义报头
            head_dic = {
                'file_name': 'test1',
                'md5': 6567657678678,
                'total_size': total_size,

            }
            # 2. json形式的报头
            head_dic_json = json.dumps(head_dic)

            # 3. bytes形式报头
            head_dic_json_bytes = head_dic_json.encode('utf-8')

            # 4. 获取bytes形式的报头的总字节数
            len_head_dic_json_bytes = len(head_dic_json_bytes)

            # 5. 将不固定的int总字节数变成固定长度的4个字节
            four_head_bytes = struct.pack('i',len_head_dic_json_bytes)

            # 6. 发送固定的4个字节
            conn.send(four_head_bytes)

            # 7. 发送报头数据
            conn.send(head_dic_json_bytes)

            # 8. 发送总数据
            conn.send(result)

        except ConnectionResetError:
            print('客户端链接中断了')
            break
    conn.close()
phone.close()

client

import socket
import struct
import json
phone = socket.socket()
phone.connect(('127.0.0.1',8848))

while 1:
    to_server_data = input('>>>输入q或者 Q 退出').strip().encode('utf-8')
    if not to_server_data:
        # 服务端如果接受到了空的内容,服务端就会一直阻塞中,所以
        # 无论哪一方发送内容时,都不能为空发送
        print('发送内容不能为空')
        continue
    phone.send(to_server_data)
    if to_server_data.upper() == b"Q":
        break
    # 1.接收固定长度的 4 个字节
    head_bytes = phone.recv(4)
    # 2.获得 bytes 类型字典的总字节数
    len_head_dic_json_bytes = struct.unpack('i',head_bytes)[0]
    # 3.接收 bytes 形式的 dic数据
    head_dic_json_bytes = phone.recv(len_head_dic_json_bytes)
    # 4.转化为json 类型 dic
    head_dic_json = head_dic_json_bytes.decode('utf-8')
    # 5.转化为字典形式的报头
    head_dic = json.loads(head_dic_json)
    '''
    head = {
    'file_name': 'test1',
    'md5':2345778832434,
    'total_size':total_size
    }
    '''
    total_data = b''
    while len(total_data) < head_dic['total_size']:
        total_data += phone.recv(1024)
    print(total_data.decode('utf-8'))
phone.close()

Based on the communication protocol udp socket

server

# 1. 基于udp协议的socket无须建立管道,先开启服务端或者客户端都行.

# 2. 基于udp协议的socket接收一个消息,与发送一个消息都是无连接的.

# 3. 只要拿到我的ip地址和端口就都可以给我发消息,我按照顺序接收消息.
import socket
server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 基于网络的UDP协议的socket
server.bind(('127.0.0.1',9000))

while 1:

    from_client_data = server.recvfrom(1024)  # 阻塞,等待客户来消息
    print(f'\033[1;35;0m来自客户端{from_client_data[1]}: {from_client_data[0].decode("utf-8")} \033[0m')
    to_client_data = input('>>>').strip()
    server.sendto(to_client_data.encode('utf-8'),from_client_data[1])

client

import socket
client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 基于网络的UDP协议的socket

while 1:

    to_server_data = input('>>>:').strip()
    client.sendto(to_server_data.encode('utf-8'),('127.0.0.1',9000))
    # data,addr = client.recvfrom(1024)
    # print(f'来自服务端{addr}消息:{data.decode("utf-8")}')

Guess you like

Origin www.cnblogs.com/hualibokeyuan/p/11366702.html