网络编程(二)

一.socket(套接字)

1.基于TCP协议的socket通信  

sever端

 1 import socket
 2 sk = socket.socket()
 3 sk.bind(('127.0.0.1',8898))  #把地址绑定到套接字
 4 sk.listen()          #监听链接
 5 conn,addr = sk.accept() #接受客户端链接
 6 ret = conn.recv(1024)  #接收客户端信息
 7 print(ret)       #打印客户端信息
 8 conn.send(b'hi')        #向客户端发送信息
 9 conn.close()       #关闭客户端套接字
10 sk.close()        #关闭服务器套接字(可选)

client端

import socket
sk = socket.socket()           # 创建客户套接字
sk.connect(('127.0.0.1',8898))    # 尝试连接服务器
sk.send(b'hello!')
ret = sk.recv(1024)         # 对话(发送/接收)
print(ret)
sk.close()            # 关闭客户套接字

2.标准通信循环

server端

import socket
server = socket.socket()  # 生成一个对象
server.bind(('127.0.0.1',8080))  # 绑定ip和port
server.listen()  # 半连接池

while True:
    conn, addr = server.accept()  
    print(addr)  # ('127.0.0.1', 51323) 客户端的地址
    while True:
        try:
            data = conn.recv(1024)
            print(data) 
            if len(data) == 0:break
            conn.send(data.upper())
        except ConnectionResetError as e:
            print(e)
            break
    conn.close()

client端

import socket

client = socket.socket()
client.connect(('127.0.0.1',8080))

while True:
    msg = input('>>>:').encode('utf-8')
    if len(msg) == 0:continue
    client.send(msg)
    data = client.recv(1024)
    print(data)

3.粘包问题

server端

import socket
import subprocess

sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()

while True:
    conn,addr = sk.accept()
    while True:
        try:
            cmd = conn.recv(1024).decode('utf-8')
            if len(cmd) == 0:break
            res = subprocess.Popen(cmd,shell= True,
                                   stderr=subprocess.PIPE,
                                   stdout=subprocess.PIPE)
            stdout = res.stdout.read()
            stderr = res.stderr.read()
            conn.send(stdout)
            conn.send(stderr)
        except ConnectionResetError:
            break

client端

import socket

sk = socket.socket()
sk.connect(('127.0.0.1',8080))

while True:
    cmd = input('请输入cmd:').strip()
    if len(cmd) == 0 :continue
    sk.send(cmd.encode('utf-8'))
    res = sk.recv(1024)
    print(res.decode('gbk'))

粘包造成的原因:

粘包现象只发生在tcp协议中:

1.从表面看,粘包问题主要是因为发送方和接收方的缓存机制,tcp协议面向流通信的特点

2.实际上,主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的

4.解决粘包

server端

import socket
import subprocess
import json
import struct
sk = socket.socket()
sk.bind(('127.0.0.1',8080))
sk.listen()

while True:
    conn,addr = sk.accept()
    while True:
        try:
            cmd = conn.recv(1024).decode('utf-8')
            if len(cmd) == 0:break
            res = subprocess.Popen(cmd,shell= True,
                                   stderr=subprocess.PIPE,
                                   stdout=subprocess.PIPE)
            stdout = res.stdout.read()
            stderr = res.stderr.read()
            ret = stdout+stderr
            head = {'name':'zzp','size':len(ret)}
            json_head = json.dumps(head)
            head_pack = struct.pack('i',len(json_head))
            sk.send(head_pack)
            sk.send(json_head.encode('utf-8'))
            sk.send(ret)
        except ConnectionResetError:
            break

client端

import socket
import struct
import json
sk = socket.socket()
sk.connect(('127.0.0.1',8080))

while True:
    cmd = input('请输入cmd:').strip()
    if len(cmd) == 0 :continue
    sk.send(cmd.encode('utf-8'))
    head_pack = sk.recv(4)
    head_len = struct.unpack('i',head_pack)[0]
    head_json = sk.recv(head_len).decode('utf-8')
    head = json.loads(head_json)
    size = head['size']
    recv_size = 0
    real_data = b''
    while recv_size < size:
        data = sk.recv(1024)
        real_data += data
        recv_size += len(data)
    print(real_data.decode('gbk'))

 

posted @ 2019-08-07 16:19  s686编程传  阅读(134)  评论(0编辑  收藏  举报