socket网络编程,黏包的化解措施

服务端:

黏包的建设方案

  1. import socket

  2. server = socket.socket()

  3. #绑定要监听的端口

  4. server.bind((‘localhost’,6969))

  5. #监听

  6. server.listen()

  7. print(“等待连接…”)

  8. #等待连接,conn正是顾客端连过来在服务端为其变化的三个总是实例

解决方案一

题指标来源于在于,接收端不亮堂发送端将在传送的字节流的长度,所以解决粘包的艺术即是环绕,怎么样让发送端在发送数据前,把温馨将在发送的字节流总大小让接收端知晓,然后接收端来七个死循环接收完全体数据。

威尼斯人6799.com 1

 

威尼斯人6799.com 2

#_*_coding:utf-8_*_
import socket,subprocess
ip_port=(‘127.0.0.1’,8080)
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

s.bind(ip_port)
s.listen(5)

while True:
conn,addr=s.accept()
print(‘客户端’,addr)
while True:
msg=conn.recv(1024)
if not msg:break
res=subprocess.Popen(msg.decode(‘utf-8’),shell=True,\
stdin=subprocess.PIPE,\
stderr=subprocess.PIPE,\
stdout=subprocess.PIPE)
err=res.stderr.read()
if err:
ret=err
else:
ret=res.stdout.read()
data_length=len(ret)
conn.send(str(data_length).encode(‘utf-8’))
data=conn.recv(1024).decode(‘utf-8’)
if data == ‘recv_ready’:
conn.sendall(ret)
conn.close()

服务端

威尼斯人6799.com 3

#_*_coding:utf-8_*_
import socket,subprocess
ip_port=('127.0.0.1',8080)
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

s.bind(ip_port)
s.listen(5)

while True:
    conn,addr=s.accept()
    print('客户端',addr)
    while True:
        msg=conn.recv(1024)
        if not msg:break
        res=subprocess.Popen(msg.decode('utf-8'),shell=True,\
                            stdin=subprocess.PIPE,\
                         stderr=subprocess.PIPE,\
                         stdout=subprocess.PIPE)
        err=res.stderr.read()
        if err:
            ret=err
        else:
            ret=res.stdout.read()
        data_length=len(ret)
        conn.send(str(data_length).encode('utf-8'))
        data=conn.recv(1024).decode('utf-8')
        if data == 'recv_ready':
            conn.sendall(ret)
    conn.close()

威尼斯人6799.com 4

威尼斯人6799.com 5

#_*_coding:utf-8_*_
import socket,time
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
res=s.connect_ex((‘127.0.0.1’,8080))

while True:
msg=input(‘>>: ‘).strip()
if len(msg) == 0:continue
if msg == ‘quit’:break

s.send(msg.encode(‘utf-8’))
length=int(s.recv(1024).decode(‘utf-8’))
s.send(‘recv_ready’.encode(‘utf-8’))
send_size=0
recv_size=0
data=b”
while recv_size < length:
data+=s.recv(1024)
recv_size+=len(data)

print(data.decode(‘utf-8’))

客户端

威尼斯人6799.com 6

#_*_coding:utf-8_*_
import socket,time
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
res=s.connect_ex(('127.0.0.1',8080))

while True:
    msg=input('>>: ').strip()
    if len(msg) == 0:continue
    if msg == 'quit':break

    s.send(msg.encode('utf-8'))
    length=int(s.recv(1024).decode('utf-8'))
    s.send('recv_ready'.encode('utf-8'))
    send_size=0
    recv_size=0
    data=b''
    while recv_size < length:
        data+=s.recv(1024)
        recv_size+=len(data)


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

威尼斯人6799.com 7

存在的问题:
程序的运行速度远快于网络传输速度,所以在发送一段字节前,先用send去发送该字节流长度,这种方式会放大网络延迟带来的性能损耗

 

  1. conn,addr = server.accept()

  2. print(“连接举办中…”)

  3. print(conn,addr)

  4.  

  5. 威尼斯人6799.com,data = conn.recv(1024)

  6. print(“recv:”,data)

  7. conn.send(data.upper())

  8. server.close()

竭泽而渔方案进级

恰恰的艺术,难点在于我们大家在殡葬

我们能够依附三个模块,那个模块能够把要发送的数目长度转换来固定长度的字节。那样顾客端每回接到音信以前若是先接受这一个一定长度字节的开始和结果看一看接下去要收到的音信大小,那么最后接受的多寡假如到达那几个值就停下,就能够刚好非常少十分多的采取完整的数量了。

客户端:

struct模块

该模块可以把贰个类型,如数字,转成固定长度的bytes

>>> struct.pack('i',1111111111111)

struct.error: 'i' format requires -2147483648 <= number <= 2147483647 #这个是范围

威尼斯人6799.com 8

威尼斯人6799.com 9

import json,struct
#假设通过客户端上传1T:1073741824000的文件a.txt

#为避免粘包,必须自定制报头
header={'file_size':1073741824000,'file_name':'/a/b/c/d/e/a.txt','md5':'8f6fbf8347faa4924a76856701edb0f3'} #1T数据,文件路径和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)

威尼斯人6799.com 10

威尼斯人6799.com 11

#_*_coding:utf-8_*_
#http://www.cnblogs.com/coser/archive/2011/12/17/2291160.html
__author__ = ‘Linhaifeng’
import struct
import binascii
import ctypes

values1 = (1, ‘abc’.encode(‘utf-8’), 2.7)
values2 = (‘defg’.encode(‘utf-8’),101)
s1 = struct.Struct(‘I3sf’)
s2 = struct.Struct(‘4sI’)

print(s1.size,s2.size)
prebuffer=ctypes.create_string_buffer(s1.size+s2.size)
print(‘Before : ‘,binascii.hexlify(prebuffer))
# t=binascii.hexlify(‘asdfaf’.encode(‘utf-8’))
# print(t)

s1.pack_into(prebuffer,0,*values1)
s2.pack_into(prebuffer,s1.size,*values2)

print(‘After pack’,binascii.hexlify(prebuffer))
print(s1.unpack_from(prebuffer,0))
print(s2.unpack_from(prebuffer,s1.size))

s3=struct.Struct(‘ii’)
s3.pack_into(prebuffer,0,123,123)
print(‘After pack’,binascii.hexlify(prebuffer))
print(s3.unpack_from(prebuffer,0))

关于struct的详实用法

威尼斯人6799.com 12

#_*_coding:utf-8_*_
#http://www.cnblogs.com/coser/archive/2011/12/17/2291160.html
__author__ = 'Linhaifeng'
import struct
import binascii
import ctypes

values1 = (1, 'abc'.encode('utf-8'), 2.7)
values2 = ('defg'.encode('utf-8'),101)
s1 = struct.Struct('I3sf')
s2 = struct.Struct('4sI')

print(s1.size,s2.size)
prebuffer=ctypes.create_string_buffer(s1.size+s2.size)
print('Before : ',binascii.hexlify(prebuffer))
# t=binascii.hexlify('asdfaf'.encode('utf-8'))
# print(t)


s1.pack_into(prebuffer,0,*values1)
s2.pack_into(prebuffer,s1.size,*values2)

print('After pack',binascii.hexlify(prebuffer))
print(s1.unpack_from(prebuffer,0))
print(s2.unpack_from(prebuffer,s1.size))

s3=struct.Struct('ii')
s3.pack_into(prebuffer,0,123,123)
print('After pack',binascii.hexlify(prebuffer))
print(s3.unpack_from(prebuffer,0))

威尼斯人6799.com 13

  1. import socket

  2.  

  3. #扬言socket类型,同期生育socket连接对象

利用struct解决黏包 

依傍struct模块,我们通晓长度数字可以被转变到三个正经尺寸的4字节数字。因而得以选用那个特点来预首发送数据长度。

发送时 接收时
先发送struct转换好的数据长度4字节 先接受4个字节使用struct转换成数字来获取要接收的数据长度
再发送数据 再按照长度接收数据

威尼斯人6799.com 14

import socket,struct,json
import subprocess
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
#就是它,在bind前加

phone.bind((‘127.0.0.1’,8080))

phone.listen(5)

while True:
conn,addr=phone.accept()
while True:
cmd=conn.recv(1024)
if not cmd:break
print(‘cmd: %s’ %cmd)

res=subprocess.Popen(cmd.decode(‘utf-8’),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
err=res.stderr.read()
print(err)
if err:
back_msg=err
else:
back_msg=res.stdout.read()

conn.send(struct.pack(‘i’,len(back_msg))) #先发back_msg的长度
conn.sendall(back_msg) #在发真实的剧情

conn.close()

服务端(自定制报头)

威尼斯人6799.com 15

import socket,struct,json
import subprocess
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加

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

phone.listen(5)

while True:
    conn,addr=phone.accept()
    while True:
        cmd=conn.recv(1024)
        if not cmd:break
        print('cmd: %s' %cmd)

        res=subprocess.Popen(cmd.decode('utf-8'),
                             shell=True,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
        err=res.stderr.read()
        print(err)
        if err:
            back_msg=err
        else:
            back_msg=res.stdout.read()


        conn.send(struct.pack('i',len(back_msg))) #先发back_msg的长度
        conn.sendall(back_msg) #在发真实的内容

    conn.close()

威尼斯人6799.com 16

威尼斯人6799.com 17

#_*_coding:utf-8_*_
import socket,time,struct

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
res=s.connect_ex((‘127.0.0.1’,8080))

while True:
msg=input(‘>>: ‘).strip()
if len(msg) == 0:continue
if msg == ‘quit’:break

s.send(msg.encode(‘utf-8’))

 

l=s.recv(4)
x=struct.unpack(‘i’,l)[0]
print(type(x),x)
# print(struct.unpack(‘I’,l))
r_s=0
data=b”
while r_s < x:
r_d=s.recv(1024)
data+=r_d
r_s+=len(r_d)

# print(data.decode(‘utf-8’))
print(data.decode(‘gbk’)) #windows默认gbk编码

客商端(自定制报头)

威尼斯人6799.com 18

#_*_coding:utf-8_*_
import socket,time,struct

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
res=s.connect_ex(('127.0.0.1',8080))

while True:
    msg=input('>>: ').strip()
    if len(msg) == 0:continue
    if msg == 'quit':break

    s.send(msg.encode('utf-8'))



    l=s.recv(4)
    x=struct.unpack('i',l)[0]
    print(type(x),x)
    # print(struct.unpack('I',l))
    r_s=0
    data=b''
    while r_s < x:
        r_d=s.recv(1024)
        data+=r_d
        r_s+=len(r_d)

    # print(data.decode('utf-8'))
    print(data.decode('gbk')) #windows默认gbk编码

威尼斯人6799.com 19

 

我们仍是能够把报头做成字典,字典里带有就要发送的下马看花数据的详细音信,然后json类别化,然后用struck将种类化后的数目长度打包成4个字节(4个自身丰盛用了)

发送时 接收时

先发报头长度

先收报头长度,用struct取出来
再编码报头内容然后发送 根据取出的长度收取报头内容,然后解码,反序列化
最后发真实内容 从反序列化的结果中取出待取数据的详细信息,然后去取真实的数据内容

威尼斯人6799.com 20

import socket,struct,json
import subprocess
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
#就是它,在bind前加

phone.bind((‘127.0.0.1’,8080))

phone.listen(5)

while True:
conn,addr=phone.accept()
while True:
cmd=conn.recv(1024)
if not cmd:break
print(‘cmd: %s’ %cmd)

res=subprocess.Popen(cmd.decode(‘utf-8’),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
err=res.stderr.read()
print(err)
if err:
back_msg=err
else:
back_msg=res.stdout.read()

headers={‘data_size’:len(back_msg)}
head_json=json.dumps(headers)
head_json_bytes=bytes(head_json,encoding=’utf-8′)

conn.send(struct.pack(‘i’,len(head_json_bytes))) #首发报头的长短
conn.send(head_json_bytes) #再发报头
conn.sendall(back_msg) #在发真实的从头到尾的经过

conn.close()

服务端:定制稍微复杂一点的报头

威尼斯人6799.com 21

import socket,struct,json
import subprocess
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #就是它,在bind前加

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

phone.listen(5)

while True:
    conn,addr=phone.accept()
    while True:
        cmd=conn.recv(1024)
        if not cmd:break
        print('cmd: %s' %cmd)

        res=subprocess.Popen(cmd.decode('utf-8'),
                             shell=True,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
        err=res.stderr.read()
        print(err)
        if err:
            back_msg=err
        else:
            back_msg=res.stdout.read()

        headers={'data_size':len(back_msg)}
        head_json=json.dumps(headers)
        head_json_bytes=bytes(head_json,encoding='utf-8')

        conn.send(struct.pack('i',len(head_json_bytes))) #先发报头的长度
        conn.send(head_json_bytes) #再发报头
        conn.sendall(back_msg) #在发真实的内容

    conn.close()

威尼斯人6799.com 22

威尼斯人6799.com 23

from socket import *
import struct,json

ip_port=(‘127.0.0.1’,8080)
client=socket(AF_INET,SOCK_STREAM)
client.connect(ip_port)

while True:
cmd=input(‘>>: ‘)
if not cmd:continue
client.send(bytes(cmd,encoding=’utf-8′))

head=client.recv(4)
head_json_len=struct.unpack(‘i’,head)[0]
head_json=json.loads(client.recv(head_json_len).decode(‘utf-8’))
data_len=head_json[‘data_size’]

recv_size=0
recv_data=b”
while recv_size < data_len:
recv_data+=client.recv(1024)
recv_size+=len(recv_data)

print(recv_data.decode(‘utf-8’))
#print(recv_data.decode(‘gbk’)) #windows默认gbk编码

客户端

威尼斯人6799.com 24

from socket import *
import struct,json

ip_port=('127.0.0.1',8080)
client=socket(AF_INET,SOCK_STREAM)
client.connect(ip_port)

while True:
    cmd=input('>>: ')
    if not cmd:continue
    client.send(bytes(cmd,encoding='utf-8'))

    head=client.recv(4)
    head_json_len=struct.unpack('i',head)[0]
    head_json=json.loads(client.recv(head_json_len).decode('utf-8'))
    data_len=head_json['data_size']

    recv_size=0
    recv_data=b''
    while recv_size < data_len:
        recv_data+=client.recv(1024)
        recv_size+=len(recv_data)

    print(recv_data.decode('utf-8'))
    #print(recv_data.decode('gbk')) #windows默认gbk编码

威尼斯人6799.com 25

 

  1. client = socket.socket()

  2. client.connect((‘localhost’,6969))

FTP作业:上传下载文件

威尼斯人6799.com 26

import socket
import struct
import json
import subprocess
import os

class MYTCPServer:
address_family = socket.AF_INET

socket_type = socket.SOCK_STREAM

allow_reuse_address = False

max_packet_size = 8192

coding=’utf-8′

request_queue_size = 5

server_dir=’file_upload’

def __init__(self, server_address, bind_and_activate=True):
“””Constructor. May be extended, do not override.”””
self.server_address=server_address
self.socket = socket.socket(self.address_family,
self.socket_type)
if bind_and_activate:
try:
self.server_bind()
self.server_activate()
except:
self.server_close()
raise

def server_bind(self):
“””Called by constructor to bind the socket.
“””
if self.allow_reuse_address:
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self.server_address)
self.server_address = self.socket.getsockname()

def server_activate(self):
“””Called by constructor to activate the server.
“””
self.socket.listen(self.request_queue_size)

def server_close(self):
“””Called to clean-up the server.
“””
self.socket.close()

def get_request(self):
“””Get the request and client address from the socket.
“””
return self.socket.accept()

def close_request(self, request):
“””Called to clean up an individual request.”””
request.close()

def run(self):
while True:
self.conn,self.client_addr=self.get_request()
print(‘from client ‘,self.client_addr)
while True:
try:
head_struct = self.conn.recv(4)
if not head_struct:break

head_len = struct.unpack(‘i’, head_struct)[0]
head_json = self.conn.recv(head_len).decode(self.coding)
head_dic = json.loads(head_json)

print(head_dic)
#head_dic={‘cmd’:’put’,’filename’:’a.txt’,’filesize’:123123}
cmd=head_dic[‘cmd’]
if hasattr(self,cmd):
func=getattr(self,cmd)
func(head_dic)
except Exception:
break

def put(self,args):
file_path=os.path.normpath(os.path.join(
self.server_dir,
args[‘filename’]
))

filesize=args[‘filesize’]
recv_size=0
print(‘—–>’,file_path)
with open(file_path,’wb’) as f:
while recv_size < filesize:
recv_data=self.conn.recv(self.max_packet_size)
f.write(recv_data)
recv_size+=len(recv_data)
print(‘recvsize:%s filesize:%s’ %(recv_size,filesize))

tcpserver1=MYTCPServer((‘127.0.0.1’,8080))

tcpserver1.run()

 

 

#下列代码与大旨非亲非故
class MYUDPServer:

“””UDP server class.”””
address_family = socket.AF_INET

socket_type = socket.SOCK_DGRAM

allow_reuse_address = False

max_packet_size = 8192

coding=’utf-8′

def get_request(self):
data, client_addr = self.socket.recvfrom(self.max_packet_size)
return (data, self.socket), client_addr

def server_activate(self):
# No need to call listen() for UDP.
pass

def shutdown_request(self, request):
# No need to shutdown anything.
self.close_request(request)

def close_request(self, request):
# No need to close anything.
pass

服务端

威尼斯人6799.com 27

import socket
import struct
import json
import subprocess
import os

class MYTCPServer:
    address_family = socket.AF_INET

    socket_type = socket.SOCK_STREAM

    allow_reuse_address = False

    max_packet_size = 8192

    coding='utf-8'

    request_queue_size = 5

    server_dir='file_upload'

    def __init__(self, server_address, bind_and_activate=True):
        """Constructor.  May be extended, do not override."""
        self.server_address=server_address
        self.socket = socket.socket(self.address_family,
                                    self.socket_type)
        if bind_and_activate:
            try:
                self.server_bind()
                self.server_activate()
            except:
                self.server_close()
                raise

    def server_bind(self):
        """Called by constructor to bind the socket.
        """
        if self.allow_reuse_address:
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind(self.server_address)
        self.server_address = self.socket.getsockname()

    def server_activate(self):
        """Called by constructor to activate the server.
        """
        self.socket.listen(self.request_queue_size)

    def server_close(self):
        """Called to clean-up the server.
        """
        self.socket.close()

    def get_request(self):
        """Get the request and client address from the socket.
        """
        return self.socket.accept()

    def close_request(self, request):
        """Called to clean up an individual request."""
        request.close()

    def run(self):
        while True:
            self.conn,self.client_addr=self.get_request()
            print('from client ',self.client_addr)
            while True:
                try:
                    head_struct = self.conn.recv(4)
                    if not head_struct:break

                    head_len = struct.unpack('i', head_struct)[0]
                    head_json = self.conn.recv(head_len).decode(self.coding)
                    head_dic = json.loads(head_json)

                    print(head_dic)
                    #head_dic={'cmd':'put','filename':'a.txt','filesize':123123}
                    cmd=head_dic['cmd']
                    if hasattr(self,cmd):
                        func=getattr(self,cmd)
                        func(head_dic)
                except Exception:
                    break

    def put(self,args):
        file_path=os.path.normpath(os.path.join(
            self.server_dir,
            args['filename']
        ))

        filesize=args['filesize']
        recv_size=0
        print('----->',file_path)
        with open(file_path,'wb') as f:
            while recv_size < filesize:
                recv_data=self.conn.recv(self.max_packet_size)
                f.write(recv_data)
                recv_size+=len(recv_data)
                print('recvsize:%s filesize:%s' %(recv_size,filesize))


tcpserver1=MYTCPServer(('127.0.0.1',8080))

tcpserver1.run()






#下列代码与本题无关
class MYUDPServer:

    """UDP server class."""
    address_family = socket.AF_INET

    socket_type = socket.SOCK_DGRAM

    allow_reuse_address = False

    max_packet_size = 8192

    coding='utf-8'

    def get_request(self):
        data, client_addr = self.socket.recvfrom(self.max_packet_size)
        return (data, self.socket), client_addr

    def server_activate(self):
        # No need to call listen() for UDP.
        pass

    def shutdown_request(self, request):
        # No need to shutdown anything.
        self.close_request(request)

    def close_request(self, request):
        # No need to close anything.
        pass

威尼斯人6799.com 28

威尼斯人6799.com 29

import socket
import struct
import json
import os

 

class MYTCPClient:
address_family = socket.AF_INET

socket_type = socket.SOCK_STREAM

allow_reuse_address = False

max_packet_size = 8192

coding=’utf-8′

request_queue_size = 5

def __init__(self, server_address, connect=True):
self.server_address=server_address
self.socket = socket.socket(self.address_family,
self.socket_type)
if connect:
try:
self.client_connect()
except:
self.client_close()
raise

def client_connect(self):
self.socket.connect(self.server_address)

def client_close(self):
self.socket.close()

def run(self):
while True:
inp=input(“>>: “).strip()
if not inp:continue
l=inp.split()
cmd=l[0]
if hasattr(self,cmd):
func=getattr(self,cmd)
func(l)

def put(self,args):
cmd=args[0]
filename=args[1]
if not os.path.isfile(filename):
print(‘file:%s is not exists’ %filename)
return
else:
filesize=os.path.getsize(filename)

head_dic={‘cmd’:cmd,’filename’:os.path.basename(filename),’filesize’:filesize}
print(head_dic)
head_json=json.dumps(head_dic)
head_json_bytes=bytes(head_json,encoding=self.coding)

head_struct=struct.pack(‘i’,len(head_json_bytes))
self.socket.send(head_struct)
self.socket.send(head_json_bytes)
send_size=0
with open(filename,’rb’) as f:
for line in f:
self.socket.send(line)
send_size+=len(line)
print(send_size)
else:
print(‘upload successful’)

 

client=MYTCPClient((‘127.0.0.1’,8080))

client.run()

客户端

威尼斯人6799.com 30

import socket
import struct
import json
import os



class MYTCPClient:
    address_family = socket.AF_INET

    socket_type = socket.SOCK_STREAM

    allow_reuse_address = False

    max_packet_size = 8192

    coding='utf-8'

    request_queue_size = 5

    def __init__(self, server_address, connect=True):
        self.server_address=server_address
        self.socket = socket.socket(self.address_family,
                                    self.socket_type)
        if connect:
            try:
                self.client_connect()
            except:
                self.client_close()
                raise

    def client_connect(self):
        self.socket.connect(self.server_address)

    def client_close(self):
        self.socket.close()

    def run(self):
        while True:
            inp=input(">>: ").strip()
            if not inp:continue
            l=inp.split()
            cmd=l[0]
            if hasattr(self,cmd):
                func=getattr(self,cmd)
                func(l)


    def put(self,args):
        cmd=args[0]
        filename=args[1]
        if not os.path.isfile(filename):
            print('file:%s is not exists' %filename)
            return
        else:
            filesize=os.path.getsize(filename)

        head_dic={'cmd':cmd,'filename':os.path.basename(filename),'filesize':filesize}
        print(head_dic)
        head_json=json.dumps(head_dic)
        head_json_bytes=bytes(head_json,encoding=self.coding)

        head_struct=struct.pack('i',len(head_json_bytes))
        self.socket.send(head_struct)
        self.socket.send(head_json_bytes)
        send_size=0
        with open(filename,'rb') as f:
            for line in f:
                self.socket.send(line)
                send_size+=len(line)
                print(send_size)
            else:
                print('upload successful')




client=MYTCPClient(('127.0.0.1',8080))

client.run()

威尼斯人6799.com 31

  1. client.send(b”hello world!”)

  2. data = client.recv(1024)

  3. print(“recv:”,data)

  4. client.close()

服务端输出:

  1. 等候连接…

  2. 连年举办中…

  3. <socket.socket fd=328,
    family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM,
    proto=0, laddr=(‘127.0.0.1’, 6969), raddr=(‘127.0.0.1’, 50248)>
    (‘127.0.0.1’, 50248)

  4. recv: b’hello world!’

顾客端输出:

  1. recv: b’HELLO WORLD!’

老是发送音讯:

服务端:

  1. import socket

  2. client = socket.socket()

  3. client.connect((‘localhost’,6969))

  1. while
    True:

  2.     msg = input(“>>:”).strip()

  3.     client.send(msg.encode(“utf-8”))

  4.     data = client.recv(1024)

  5.     print(“recv:”,data.decode())

  6. client.close()

客户端:

  1. import socket

  2.  

  3. #宣称socket类型,同不时间生育socket连接对象

  1. client = socket.socket()

  2. client.connect((‘localhost’,6969))

  1. client.send(b”hello world!”)

  2. # client.send(“我要下载”.encode(“utf-8”))

  3. data = client.recv(1024)

  4. print(“recv:”,data)

  5. client.close()

在linux上客商端试行命令

服务端:

  1. [root@test-c2c-console01 oldboy]#
    cat socket_server.py

  2. #-*-coding:utf-8-*-

  3. #_author_=”golden”

  4. #服务端

  5. import socket

  6. import os

  7.  

  8. server = socket.socket()

  9. #绑定要监听的端口

  10. server.bind((‘localhost’,6969))

  11. #监听,最罗安达接数

  12. server.listen(5)

  13. print(“等待连接…”)

  14. while
    True:

  15.     #conn即是客商端连过来在服务端为其转移的八个接二连三实例

  1.     conn,addr = server.accept()

  2.     print(“连接进行中…”)

  3.     print(conn,addr)

  4.     while True:

  5.         data = conn.recv(1024)

  6.         print(“recv:”,data)

  7.         if not data:

  8.             print(“顾客端断开!”)

  9.             break

  10.         res = os.popen(data).read()

  1.         conn.send(res)

  2. server.close()

客户端:

  1. [root@test-c2c-console01 oldboy]#
    cat socket_client.py

  2. #-*-coding:utf-8-*-

  3. _author_ = “golden”

  4. #客户端

  5. import socket

  6. #扬言socket类型,相同的时候生成socket连接对象

  1. client = socket.socket()

  2. client.connect((‘localhost’,6969))

  1. while
    True:

  2.     msg = raw_input(“>>:”).strip()

  3.     if
    len(msg) == 0:continue

  4.     client.send(msg.encode(“utf-8”))

  5.     data = client.recv(102400)

  6.     print(data.decode())

  7.  

  8. client.close()

linux发送文书

服务端:

  1. [root@test-c2c-console01 oldboy]#
    cat socket_server.py

  2. #-*-coding:utf-8-*-

  3. #_author_=”golden”

  4. #服务端

  5. import socket

  6. import os

  7.  

  8. server = socket.socket()

  9. #绑定要监听的端口

  10. server.bind((‘localhost’,6969))

  11. #监听,最都林接数

  12. server.listen(5)

  13. print(“等待连接…”)

  14. while
    True:

  15.     #conn正是客商端连过来在服务端为其变化的三个连接实例

  1.     conn,addr = server.accept()

  2.     print(“连接进行中…”)

  3.     print(conn,addr)

  4.     while True:

  5.         data = conn.recv(1024)

  6.         print(“recv:”,data)

  7.         if not data:

  8.             print(“客商端断开!”)

  9.             break

  10.         #res = os.popen(data).read()

  1.         #conn.send(res)

  2.         f = open(“move.mkv”)

  3.         data = f.read()

  4.         conn.send(data)

  5. server.close()

客户端:

  1. [root@test-c2c-console01 oldboy]#
    cat socket_client.py

  2. #-*-coding:utf-8-*-

  3. _author_ = “golden”

  4. #客户端

  5. import socket

  6. #宣示socket类型,同临时候生成socket连接对象

  1. client = socket.socket()

  2. client.connect((‘localhost’,6969))

  1. while
    True:

  2.     msg = raw_input(“>>:”).strip()

  3.     if
    len(msg) == 0:continue

  4.     client.send(msg.encode(“utf-8”))

  5.     data = client.recv(102400)

  6.     #print(data.decode())

  7.     f = open(“video.avi”,’wb’)

  8.     f.write(data)

  9.     f.close()

  10.  

  11. client.close()

一回最多发送的数据量32768(分裂系统有分别)

  1. [root@test-c2c-console01 oldboy]# ll
    *.avi *.mkv

  2. -rw-r–r– 1 root root 681790584 Dec 27
    19:26 move.mkv

  3. -rw-r–r– 1 root root 32768 Feb 12
    08:47 video.avi

多次出殡和埋葬

服务端:

  1. [root@test-c2c-console01 oldboy]#
    cat socket_server.py

  2. #-*-coding:utf-8-*-

  3. #_author_=”golden”

  4. #服务端

  5. import socket

  6. import os

  7.  

  8. server = socket.socket()
    #实例化贰个socket

  9. #绑定要监听的端口

  10. server.bind((‘localhost’,6969))

  11. #监听,最罗安达接数

  12. server.listen(5)

  13. print(“等待连接…”)

  14. while
    True:

  15.     #conn就是客商端连过来在服务端为其变化的贰个总是实例

  1.     conn,addr = server.accept()

  2.     print(“连接实行中…”)

  3.     print(conn,addr)

  4.     while True:

  5.         data = conn.recv(1024)

  6.         print(“recv:”,data)

  7.         if not data:

  8.             print(“客商端断开!”)

  9.             break

  10.         #res = os.popen(data).read()

  1.         #conn.send(res)

  2.         f = open(“move.mkv”)

  3.         data = f.read()

  4.         print(len(data))

  5.         conn.send(data)

  6. server.close()

客户端:

  1. [root@test-c2c-console01 oldboy]#
    cat socket_client.py

  2. #-*-coding:utf-8-*-

  3. _author_ = “golden”

  4. #客户端

  5. import socket

  6. #宣称socket类型,同一时间生成socket连接对象

  1. client = socket.socket()

  2. client.connect((‘localhost’,6969))

  1. f = open(“video.avi”,’wb’)

  2. while
    True:

  3.     msg = raw_input(“>>:”).strip()

  4.     if
    len(msg) == 0:continue

  5.     client.send(msg.encode(“utf-8”))

  6.     data = client.recv(102400)

  7.     #print(data.decode())

  8.     f.write(data)

  9.     f.flush()

  10.  

  11. client.close()

每交互二次文件的变型:

  1. [root@test-c2c-console01 oldboy]# ll
  1. total 665832

  2. -rw-r–r– 1 root root 681790584 Dec 27
    19:26 move.mkv

  3. -rw-r–r– 1 root root 0 Feb 12 09:08
    video.avi

  4. [root@test-c2c-console01 oldboy]# ll

  1. total 665864

  2. -rw-r–r– 1 root root 681790584 Dec 27
    19:26 move.mkv

  3. -rw-r–r– 1 root root 32768 Feb 12
    09:08 video.avi

  4. [root@test-c2c-console01 oldboy]# ll

  1. total 665964

  2. -rw-r–r– 1 root root 681790584 Dec 27
    19:26 move.mkv

  3. -rw-r–r– 1 root root 135168 Feb 12
    09:08 video.avi

  4. [root@test-c2c-console01 oldboy]# ll

  1. total 666164

  2. -rw-r–r– 1 root root 681790584 Dec 27
    19:26 move.mkv

  3. -rw-r–r– 1 root root 339968 Feb 12
    09:09 video.avi

  4. [root@test-c2c-console01 oldboy]# ll

  1. total 666164

  2. -rw-r–r– 1 root root 681790584 Dec 27
    19:26 move.mkv

  3. -rw-r–r– 1 root root 339968 Feb 12
    09:09 video.avi

socket实现轻巧的ssh

服务端:

  1. import socket,os

  2. server = socket.socket()

  3. server.bind((‘localhost’,9999))

  4. server.listen()

  5. while
    True:

  6.     conn,addr = server.accept()

  7.     print(“new conn:”,addr)

  8.     while True:

  9.         data = conn.recv(1024)

  10.         if not data:

  11.             print(“客商端已断开!”)

  12.             break

  13.         print(“实践命令:”,data)

  14.         cmd_res =
    os.popen(data.decode()).read() #收到字符串,试行结果也是字符串

  1.         print(“before send “,len(cmd_res))

  2.         if len(cmd_res) ==0:

  3.             cmd_res = “cmd has no output”

  4.         conn.send(str(len(cmd_res.encode())).encode(“utf-8”))#头阵大小给顾客端

  5.         conn.send(cmd_res.encode(“utf-8”))

  6.  

  7. server.close()

客户端:

  1. import socket

  2. client = socket.socket()

  3. client.connect((‘localhost’,9999))

  1.  

  2. while
    True:

  3.     cmd = input(“>>:”).strip()

  4.     if
    len(cmd) == 0:continue

  5.     client.send(cmd.encode(“utf-8”))

  6.     cmd_res_size =
    client.recv(1024)#接过大小

  7.     print(“结果大小:”,cmd_res_size)

  8.     received_size = 0

  9.     received_data = b”

  10.     while received_size < int(cmd_res_size.decode()):

  11.         data = client.recv(1024)

  1.         received_size += len(data)
    #每回收到的有非常的大可能率低于1024,所以必得用len推断

  2.         # print(data.decode())

  3.         received_data += data

  4.     else:

  5.         print(“cmd res receive
    done…”,received_size)

  6.         print(received_data.decode())

  1.  

  2. client.close()

瞩目socket粘包难点。

方法一:在多个相连的send之间增多sleep。

  1. conn.send(str(len(cmd_res.encode())).encode(“utf-8”))#头阵大小给顾客端

  2. time.sleep(0.5)

  3. conn.send(cmd_res.encode(“utf-8”))

格局二:在历次send之后张开贰遍交互。

服务端:

  1. conn.send(str(len(cmd_res.encode())).encode(“utf-8”))#首发大小给顾客端client_ack
    = conn.recv(1024) #wait client to confirm

  2. print(client_ack.decode())

  3. conn.send(cmd_res.encode(“utf-8”))

客户端:

  1. cmd_res_size =
    client.recv(1024)#摄取大小

  2. client.send(“已图谋好接收数据!”.encode(“utf-8”))

socket实现轻松的ftp

ftp server:

1、读取文件名

2、检查实验文件是或不是留存

3、张开文件

4、检查测试文件大小

5、发送文件大小给客户端

6、等待顾客端确认

7、起始边读边发数据

8、发送md5

服务端:

  1. import socket,os,hashlib

  2. server = socket.socket()

  3. server.bind((“localhost”,9999))

  4. server.listen()

  5. while
    True:

  6.     conn,addr = server.accept()

  7.     print(“new conn:”,addr)

  8.     while True:

  9.         print(“等待指令…”)

  10.         data = conn.recv(1024)

  11.         if not data:

  12.             print(“顾客端已断开!”)

  13.             break

  14.         cmd,filename =
    data.decode().split()

  15.         print(filename)

  16.         if os.path.isfile(filename):

  17.             f = open(filename,”rb”)

  18.             m = hashlib.md5()

  19.             file_size =
    os.stat(filename).st_size

  20.             conn.send(str(file_size).encode())
    #send file size

  21.             conn.recv(1024) #wait
    for ack

  22.             for line in f:

  23.                 m.update(line)

  24.                 conn.send(line)

  25.             print(“file md5”,m.hexdigest())

  26.             f.close()

  27.             conn.send(m.hexdigest().encode())
    #sed med5

  28.         print(“send done”)

  29.  

  30. server.close()

客户端:

  1. import socket,hashlib

  2. client = socket.socket()

  3. client.connect((‘localhost’,9999))

  1. while
    True:

  2.     cmd = input(“>>:”).strip()

  3.     if
    len(cmd) == 0:continue

  4.     if
    cmd.startswith(“get”):

  5.         client.send(cmd.encode())

  1.         server_response =
    client.recv(1024)

  2.         print(“server_response:”,server_response)

  1.         client.send(b”read to recv file”)

  2.         file_total_size = int(server_response.decode())

  3.         received_size = 0

  4.         filename = cmd.split()[1]

  1.         f = open(filename + “.new”,”wb”)

  2.         m = hashlib.md5()

  3.         while received_size <
    file_total_size:

  4.             if file_total_size –
    received_size > 1024:

  5.                 size = 1024

  6.             else:

  7.                 size =
    file_total_size – received_size

  8.  

  9.             data = client.recv(size)

  1.             received_size += len(data)
  1.             m.update(data)

  2.             f.write(data)

  3.             #
    print(file_total_size,received_size)

  4.         else:

  5.             new_file_md5 =
    m.hexdigest()

  6.             print(“file recv
    done”,received_size,file_total_size)

  7.             f.close()

  8.         server_file_md5 =
    client.recv(1024)

  9.         print(“server file md5:{0},client file
    md5:{1}”.format(server_file_md5,new_file_md5))

  10. client.close()

SocketServer

福如东海产出管理。

The socketserver module simplifies the task of writing network servers.

socketserver常用项目

class
socketserver.TCPServer(server_address,RequestHandlerClass,bind_and_activate=True)

This uses the Internet TCP protocol,which provides for continuous
streams of data between the client and server.

class
socketserver.UDPServer(server_address,RequestHandlerClass,bind_and_activate=True)

This uses datagrams,which are discrete packets of information that may
arrive out of order or be lost while in transit.The parameters are the
same as for TCPServer.

创建三个socketserver至少分一下几步:

1、You mast create a request handler class by subclassing the
BaseRequestHandler class and overriding its handle() method;this method
will process incoming requests.

成立三个必要管理类承接BaseRequestHandler,何况重写父类handle()。

2、You mast instantiate one of the server classes,passing it the
server’s address and the request handler class.

实例化TCPServer,并传递server ip和上述创设的央求管理类给这些TCPServer。

3、Then call the handle_request() or server_forever() method of the
server object to process one or many requests.

server.handle_request():只处理多少个呼吁

server.server_forever():管理多少个必要

4、Call server_close() to close the socket.

服务端:

  1. import socketserver

  2.  

  3. class
    MyTCPHandler(socketserver.BaseRequestHandler):

  4.  

  5.     def handle(self):

  6.         while True:

  7.             try:

  8.                 self.data =
    self.request.recv(1024).strip()

  9.                 print(“{} wrote
    :”.format(self.client_address[0]))

  10.                 print(self.data)

  1.                 self.request.send(self.data.upper())
  1.             except ConnectionResetError
    as CR:

  2.                 print(“err”,CR)

  3.                 break

  4.  

  5. if
    __name__ == “__main__”:

  1.     HOST,PORT = “localhost”,9999

  2.     # server =
    socketserver.TCPServer((HOST,PORT),MyTCPHandler) # 单线程

  3.     server =
    socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler) #
    多线程,ForkingTCPServer多进程

  4.     server.serve_forever()

客户端:

  1. import socket

  2.  

  3. client = socket.socket()

  4. client.connect((“localhost”,9999))

  5. while
    True:

  6.     msg = input(“>>:”).strip()

  7.     if
    len(msg) == 0:continue

  8.     client.send(msg.encode(“utf-8”))

  9.     data = client.recv(1024)

  10.     print(“recv:”,data.decode())

  11. client.close()

拉开一个新线程

  1. def process_request(self, request,
    client_address):

  2.     “””Start a new thread to process the request.”””

  1.     t = threading.Thread(target =
    self.process_request_thread,

  2.                          args =
    (request, client_address))

  3.     t.daemon = self.daemon_threads

  1.     t.start()  

相关文章