Python socket服务常用操作代码实例
套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。
1.实现客户端发送字符,服务器返回大写的字符:
服务器:
importsocketserver
classMyTCPHandler(socketserver.BaseRequestHandler):#通过类的继承,实现
defhandle(self):#重写父类的handle方法,所有的操作都在此方法中
whileTrue:#循环,不停的接收从客户端来的数据
try:
self.data=self.request.recv(1024).strip()#从客户端接收数据,每次收1024字节
print("{}send:".format(self.client_address),self.data)
self.request.send(self.data.upper())#从服务器发送给客户端数据
exceptConnectionResetErrorase:
print('Error:',e)
break
if__name__=='__main__':
host,port='localhost',9999
server=socketserver.ThreadingTCPServer((host,port),MyTCPHandler)#通过多线程实现多个客户端连接,每个客户端连接都是一个线程
server.serve_forever()#一直运行服务
客户端:
importsocket
client=socket.socket()#socket对象
client.connect(('localhost',9999))#连接服务器地址和端口
whileTrue:#循环,不停的输入发送数据
con=input('>>>:').strip()
iflen(con)==0:continue#不能发送空数据,否则会阻塞
client.send(con.encode('utf-8'))#发送数据,必须是二进制的
data=client.recv(1024)#接收服务器返回的数据
print(data.decode())#打印解码后的数据
client.close()#关闭
2.通过socket执行服务器命令:
用法:直接在客户端输入处输入命令如:ipconfig
服务器:
importsocket
importos
importthreading
deftcplink(sock,addr):
print('Acceptnewconnectionfrom%s:%s...'%addr)
whileTrue:#和每个接入的客户端,进行多次数据通信
data=sock.recv(1024)#接收客户端数据
ifnotdataordata.decode('utf-8')=='exit':#如果客户端不发送数据或者发送了exit
print('clientdisconnected.')
break
content=os.popen(data.decode('utf-8')).read()#对发送来的数据执行cmd命令,获取结果
iflen(content)==0:#如果执行的命令结果为空的,就手动造一个结果。因为如果为空数据,会挂起,无法正常发送。
content='cmdnotexists.'
sock.send(str(len(content.encode('utf-8'))).encode('utf-8'))#发送数据的长度
print('sendlength:',(len(content.encode('utf-8'))))
#print('content,',content.encode('utf-8'))
recv=sock.recv(1024)#因为上下都有一个send连在一起,可能发生粘包现象,为了防止这种情况,可以让客户端重新应答一下
print('Answer:',recv.decode('utf-8'))
sock.send(content.encode('utf-8'))#发送数据
print('sendfinished.')
sock.close()
print('Connectionfrom%s:%sclosed.'%addr)
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#监听端口:
s.bind(('127.0.0.1',9999))
s.listen(3)
print('Waitingforconnection...')
whileTrue:
#接受一个新连接:
sock,addr=s.accept()
#创建新线程来处理TCP连接:
t=threading.Thread(target=tcplink,args=(sock,addr))
t.start()
客户端:
importsocket
#AF_INET代表ipv4,SOCK_STREAM代表TCP
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#确定网络协议,生成对象
s.connect(('127.0.0.1',9999))#连接服务器的地址和端口,元组的形式。
whileTrue:
msg=input('>>:').strip()
iflen(msg)!=0:#如果消息为空,会一直挂起,所以不能为空
ifmsg=='exit':
s.close()#关闭连接
print('Connectionclosed.')
break
s.send(msg.encode('utf-8'))#给服务器发送数据,必须是二进制的
length=s.recv(1024)#首先接收服务器返回的将要接收的数据的长度信息。
s.send(b'Readytoreceive...')#发送接收命令
length=int(length.decode('utf-8'))
print('receivelen:',length)
data_len=0
data_recv=b''
whiledata_len
3.通过socket传输文件:
用法:get文件名
服务器:
importsocket
importos
importhashlib
importthreading
deftcplink(sock,addr):
print('Acceptnewconnectionfrom%s:%s...'%addr)
whileTrue:#和每个接入的客户端,进行多次数据通信
data=sock.recv(1024)#接收客户端数据
ifnotdataordata.decode('utf-8')=='exit':#如果客户端不发送数据或者发送了exit
print('clientdisconnected.')
break
oper,filename=data.decode('utf-8').split()#对接收的数据按照空格分割
ifoper=='get':
m=hashlib.md5()
ifos.path.isfile(filename):
size=os.stat(filename).st_size#获取文件大小
print('Sendsize:',size)
sock.send(str(size).encode('utf-8'))#发送文件大小
recv=sock.recv(1024)#接收客户端确认信息(因为上下文两个send是连着的,所以为了防止粘包,接收一次信息)
f=open(filename,'rb')
forlineinf:
sock.send(line)#读取文件,发送给客户端
m.update(line)
#print('Sendfinished.',m.hexdigest())#打印md5的值
sock.send(m.hexdigest().encode('utf-8'))#把md5的值发送给客户端
sock.close()
print('Connectionfrom%s:%sclosed.'%addr)
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#监听端口:
s.bind(('127.0.0.1',9999))
s.listen(3)
print('Waitingforconnection...')
whileTrue:
#接受一个新连接:
sock,addr=s.accept()
#创建新线程来处理TCP连接:
t=threading.Thread(target=tcplink,args=(sock,addr))
t.start()
客户端:
importsocket
importhashlib
#AF_INET代表ipv4,SOCK_STREAM代表TCP
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#确定网络协议,生成对象
s.connect(('127.0.0.1',9999))#连接服务器的地址和端口,元组的形式。
whileTrue:
msg=input('>>:').strip()
iflen(msg)!=0:#如果消息为空,会一直挂起,所以不能为空
ifmsg=='exit':
s.close()#关闭连接
print('Connectionclosed.')
break
s.send(msg.encode('utf-8'))#给服务器发送数据,必须是二进制的
length=s.recv(1024)#首先接收服务器返回的将要接收的数据的长度信息。
s.send(b'Readytoreceive...')#发送接收确认命令
length=int(length.decode('utf-8'))
print('Recvsize:',length)
data_len=0
data_recv=b''
#新文件名
fileName=msg.split()[-1].split('.')[0]
fileExt=msg.split()[-1].split('.')[-1]
newFile=fileName+'-1.'+fileExt
f=open(newFile,'wb')#打开文件,准备写入服务器发过来的文件
m=hashlib.md5()
whiledata_len1024:#如果剩下的信息长度大于1024,即不能一次性发完。
size=1024
else:#如果能一次性发完,就只收剩下的信息。目的是准确的接收文件的大小,把可能粘连的send的数据留给下一次recv
size=length-data_len
data=s.recv(size)#从服务器接收数据
f.write(data)
m.update(data)
data_len+=len(data)
f.close()
print('recv_md5:',m.hexdigest())#打印返回的数据。
recv=s.recv(1024)#接收下一次send的数据,即md5的值。
print('orig_md5:',recv.decode())
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。