您的位置:首页 > 编程语言 > Python开发

Python socket 通信

2016-07-12 19:10 375 查看
最近在做论文实验,涉及到有关于socket通信的内容,在此做一个总结。


关于Socket的基本内容,我是看了这篇博客,来自于点击打开链接,里面涉及到了有关Python 中socket通信的基本知识。下面介绍一下基于TCP的socket通信基本代码

Server

#server

import socket
import pickle  #python 的序列化模块
local=('127.0.0.1', 5000)  #绑定的地址和端口号
server=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(local)
server.listen(1)
conn,addr=server.accept()
data=pickle.loads(conn.recv(1024))
conn.close()
Client

#Client

import socket
import pickle

addr=('127.0.0.1',5000)
client=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(addr)
data="hello world"
client.sendall(pickle.dumps(data)) #python3 总sendall()只能发送字节数据,需要通过pickle模块序列化数据
client.close()
上面可以实现简单的socket模块的通信,利用pickle模块我们可以实现发送list,tuple等数据,只需要pickle.dumps(list)后发送数据。

下面说一下子啊具体实验过程中遇到的一些问题,以及自己网上搜到的一些解决方法。

主要的问题是

client.sendall(pickle.dumps(data))
<pre name="code" class="python">data=pickle.loads(conn.recv(1024))



在运行时server端会报如下错误:
ran out of input

主要原因是发送的data数据量太大导致了server端无法完全接受,

conn.recv(1024)


接受的最大字节数为1024,如果数据量不是太大,可以改为

conn.recv(1024*10)
即可解决报错的问题。不过我试了一下太大的数据这样做不行,我有次改为

conn.recv(1024*10000)
发送还是会报错,证明这不是一个好方法。

然后想到的方法是将大量数据线保存成文件,在发送文件到Server端,解析出数据,代码如下

#server

import socket
import pickle  #python 的序列化模块
local=('127.0.0.1', 5000)  #绑定的地址和端口号
server=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(local)
server.listen(1)
conn,addr=server.accept()
f=open('data','wb') #以wb模式打开data文件,wb代表以字节形式写入文件
while True:
<span style="white-space:pre">	</span>message=conn.recv(1024)
<span style="white-space:pre">	</span>if not message:
<span style="white-space:pre">		</span>break
<span style="white-space:pre">	</span>f.write(message)
f.close()
f=open('data','rb')
data=pickle.load(f) #pickle 的load()函数从一个具有read()或readline()方法的对象中恢复数据
f.close()
conn.close()


#Client

import socket
import pickle

addr=('127.0.0.1',5000)
client=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(addr)
f=open('message','wb')
pickle.dump(message,f)
f.close()
f=open('message','rb')
while 1:
   data=f.read(1024)
   if not data:
        break
   s.send(data)
f.close()
client.close()
client.close()


后来在网上搜索发现了另一种简单的方法,如果事先知道要传输的数据的大小,可以将其长度加在发送的数据前面,发送过去,具体如下:

#server
import socket
import struct
import pickle
Host='127.0.0.1'
port=5007
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((Host,port))
s.listen(1)
coon,addr=s.accept()
buff=b''
buff=coon.recv(2)  #这里2 是Client端中length的长度大小
length=struct.unpack('!H',buff)[0]
data=pickle.loads(coon.recv(length))
print(data)
coon.close()


#client
import socket
import struct
import pickle
Host='127.0.0.1'
port=5007
data="hello world"
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((Host,port))
packet=pickle.dumps(data)
length=struct.pack('!H',len(packet))
s.sendall(length)
s.sendall(packet)
s.close()
最后发现了另一种最简便的方法:利用multiprocessing.connection 模块的Client和Listener,可以不将数据序列化传输,并且不用指定数据的大小,具体代码如下:

#server
from multiprocessing.connection import Listener
Host='127.0.0.1'
port=5007
server=Listener((Host,port))
conn=server.accept()
data=conn.recv()
conn.close()


#client
from multiprocessing.connection import Client
Host='127.0.0.1'
port=5007
data="hello world"
client=Client((Host,port))
client.send(data)
client.close()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: