네트워크 프로그래밍의 기초

서브 프로세스 모듈

: 액션
1 단말은 운영 시스템 코드 실행 명령 수
(2)의 결과를, 상기 단말기는 실행을 반환

    用法:
    import subprocess
    
    cmd = inpu('CMD >>>')
    obj = subprocess.Popen(
        cmd.decode('utf8'), 
        shell=True,
        stdout= subprocess.PIPE,
        stderr= subprocess.PIPE
        )
    result = obj.stdout.read() + obj.stderr.read()
    
    print(result.decode('gbk'))

TCP 프로토콜

특성 : 이것은 스트리밍 프로토콜, 적은 양의 데이터가 연속적으로 송신 할 복수 회, 하나 개의 시간 간격이 짧은 데이터 패키지가 전송되는이며

패키지 끈적 문제

이유 :

(1) 수신 된 데이터의 길이가 필요로 예측할 수
2 연속 데이터 전송량 복수 작고, 데이터의 짧은 시간 간격은 일회용 포장을 전송.

패키지는 끈적 문제를 해결하기 위해 : 데이터의 끝의 정확한 길이를 말한다.
-struct 모듈 :

헤더, 데이터 전송되어야한다 :
1 커스텀 헤더, 사전에 이러한 기술 정보로서 생성 된 데이터의 데이터 길이는
(2), 사전 json.dumps 직렬화 및 송신 바이트로 부호화
3 상기 제 1 패킷의 헤더의 길이, 다음 struct.pack (4 바이트)와 고정 된 길이로 포맷
4 전송 : 그 1 헤더 길이, 다음의 전송 헤더를 전송하고, 상기 데이터 본체를 보낸다

수신 :

도 1을 참조하면, 먼저 네 개의 바이트 헤더의 길이 정보는 헤더의 길이 값을 압축하는 압축하는 접수

2. json.load 얻어진 수신 된 헤더의 헤더 값, 및 디코딩 된 텍스트 데이터의 길이 (데이터 길이를 포함)의 설명 정보를 직렬화

(3) 본체의 데이터 길이에 따라 상기 수신 된 데이터,

사용법 :

import json,struct
#假设通过客户端上传10G:10000000的文件:小视频.txt

#为避免粘包,必须自定制报头
header={'file_size':10000000,'file_name':'小视频.txt', 'md5':'8f6fbf8347faa4924a76856701edb0f3'} #10G数据,文件路径和md5值

#为了该报头能传送,需要序列化并且转为bytes
head_bytes=bytes(json.dumps(header),encoding='utf-8') #序列化并转成bytes,用于传输

#为了让客户端知道报头的长度,用struck将报头长度这个数字转成固定长度:4个字节
head_len_bytes=struct.pack('i',len(head_bytes)) #这4个字节里只包含了一个数字,该数字是报头的长度

#客户端开始发送
conn.send(head_len_bytes) #先发报头的长度,4个bytes
conn.send(head_bytes) #再发报头的字节格式
conn.sendall(文件内容) #然后发真实内容的字节格式

#服务端开始接收
head_len_bytes=s.recv(4) #先收报头4个bytes,得到报头长度的字节格式
x=struct.unpack('i',head_len_bytes)[0] #提取报头的长度

head_bytes=s.recv(x) #按照报头长度x,收取报头的bytes格式
header=json.loads(json.dumps(header)) #提取报头

#最后根据报头的内容提取真实的数据,比如
real_data_len=s.recv(header['file_size'])
s.recv(real_data_len)

큰 파일을 업로드

예를 들어 비디오를 업로드하려면 :

클라이언트 :

import socket
import struct
import json

client = socket.socket()

client.connect(
    ('127.0.0.1', 9527)
)

with open(r'C:\day 027\5 上传大文件.mp4', 'rb')as f:
    movie_bytes = f.read()

head_dic = {
    'file_name': '5 上传大文件.mp4',
    'file_size': len(movie_bytes)
}

json_head = json.dumps(head_dic)

bytes_head = json_head.encode('utf-8')

headers = struct.pack('i', len(bytes_head))

client.send(headers)
client.send(bytes_head)

init_data = 0
num = 1
with open(r'C:\day 027\5 上传大文件.mp4', 'rb')as f:
    while init_data < len(movie_bytes):
        send_data = f.read(1024)
        num += 1
        client.send(send_data)
        print(send_data, f'第{num}段数据发送完成')
        init_data += len(send_data)
    print('发送完毕!')


서버 :

import socket
import json
import struct

server = socket.socket()
server.bind(
    ('127.0.0.1', 9527)
)
server.listen(5)

while True:
    conn, addr = server.accept()
    try:

        headers = conn.recv(4)

        head_len = struct.unpack('i', headers)[0]

        byte_head = conn.recv(head_len)

        head_dic = json.loads(byte_head.decode('utf-8'))
        print(head_dic)

        file_name = head_dic.get('file_name')
        file_size = head_dic.get('file_size')

        init_data = 0
        num = 1
        with open(file_name, 'wb') as f:

            while init_data < file_size:
                data = conn.recv(1024)
                print(f'第{num}段',data)
                f.write(data)
                init_data += len(data)
            print(f'{file_name}接收完毕!')

    except Exception as e:
        print('error:', e)
        break
conn.close()

UDP

UDP는 전송 프로토콜
양방향 파이프를 확립 할 필요가 없습니다, 1
2,하지 끈적 가방
말에 서비스를 기다리지 않고 3, 클라이언트가 서버에게 데이터의 수신을 보냅니다
4, 서버는 데이터만을 수신 할 필요가 수신 아무리 많은 고객이 통과 오지

서버 :

import socket

server = socket.socket(type=socket.SOCK_DGRAM)

server.bind(
    ('127.0.0.1', 9527)
)

msg1 = server.recvfrom(1024)
msg2 = server.recvfrom(1024)
msg3 = server.recvfrom(1024)

print(msg1, msg2, msg3)

클라이언트 :

import socket

client =socket.socket(type=socket.SOCK_DGRAM)

server_ip_port = ('127.0.0.1', 9527)

client.sendto(b'hello!', server_ip_port)
client.sendto(b'hello!', server_ip_port)
client.sendto(b'hello!', server_ip_port)
client.sendto(b'hello!', server_ip_port)
client.sendto(b'hello!', server_ip_port)

결과 : (b'hello '('127.0.0.1 ', 57182) (b'hello!)'( '127.0.0.1', 57182)) (b'hello '('127.0.0.1 '! , 57182))

간단한 채팅 룸

여러 클라이언트 간단한 채팅 룸에 대한 소켓 서버 소켓을 구현하는 TCP 프로토콜을 기반으로 :

서버 :

import socket

server = socket.socket(type=socket.SOCK_DGRAM)

server.bind(
    ('127.0.0.1', 9527)
)

while True:

    # 服务端接收客户端传过来的消息
    msg, addr = server.recvfrom(1024)  # (消息,客户端地址)
    msg1, addr1 = server.recvfrom(1024)  # (消息,客户端地址)
    msg2, addr2 = server.recvfrom(1024)  # (消息,客户端地址)

    print(addr)
    print(addr1)
    print(addr2)
    print(msg.decode('utf-8'))
    print(msg1.decode('utf-8'))
    print(msg2.decode('utf-8'))

    # 服务端往客户端发送消息
    send_msg = input('服务端发送消息:').encode('utf-8')
    server.sendto(send_msg, addr)
    server.sendto(send_msg, addr1)
    server.sendto(send_msg, addr2)

클라이언트 1 :

import socket

client = socket.socket(type=socket.SOCK_DGRAM)

server_ip_port = ('127.0.0.1', 9527)

while True:
    send_msg = input('客户端1: ').encode('utf-8')

    # 发送消息必须要加上对方地址
    client.sendto(send_msg, server_ip_port)

    # 能接收任何人的消息
    msg = client.recv(1024)

    print(msg.decode('utf-8'))

클라이언트 2 :

import socket

client = socket.socket(type=socket.SOCK_DGRAM)

server_ip_port = ('127.0.0.1', 9527)

while True:
    send_msg = input('客户端2: ').encode('utf-8')

    # 发送消息必须要加上对方地址
    client.sendto(send_msg, server_ip_port)

    # 能接收任何人的消息
    msg = client.recv(1024)

    print(msg.decode('utf-8'))

클라이언트 3 :

import socket

client = socket.socket(type=socket.SOCK_DGRAM)

server_ip_port = ('127.0.0.1', 9527)

while True:
    send_msg = input('客户端3: ').encode('utf-8')

    # 发送消息必须要加上对方地址
    client.sendto(send_msg, server_ip_port)

    # 能接收任何人的消息
    msg = client.recv(1024)

    print(msg.decode('utf-8'))

먼저 서버를 시작한 다음 차례에서 클라이언트를 시작, 시뮬레이션 대화방을 시작할 수 있습니다

SocketServer

파이썬은 내장 된 모듈은 소켓 소켓 서버 코드를 단순화하는 데 사용할 수있다

import socket

class MyTcpServer(socketserver, BaseRequestHandler):
    def handler(self):
        
        data = self.request.recv(1024)
        pirnt(data)
        send_msg = input('服务端:').encode('utf8')
        self.request.send(send_msg)

추천

출처www.cnblogs.com/allenchen168/p/11711218.html