基础版
server code
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8080))
phone.listen(5)
print('starting...')
conn,client_addr=phone.accept()
# print(phone)
# print(conn)
# print(client_addr)
data=conn.recv(1024)
print('客户端数据',data.decode('UTF-8'))
conn.send(data.upper())
conn.close()
phone.close()
client code
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8080))
phone.send('hello world'.encode('utf-8'))
data=phone.recv(1024)
print(data)
phone.close()
基础版+循环执行
sever code
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8081))
phone.listen(5)
print('starting...')
conn,client_addr=phone.accept()
print(client_addr)
while True:
# print(phone)
# print(conn)
# print(client_addr)
data=conn.recv(1024)
print('客户端数据',data.decode('UTF-8'))
conn.send(data.upper())
conn.close()
phone.close()
client code
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8081))
while True:
msg=input('>> ')
phone.send(msg.encode('utf-8'))
data=phone.recv(1024)
print(data)
phone.close()
server code bug fix
上述server code代码有一个bug, 就是当client端断开的时候, 如果是linux操作系统, 会陷入一个死循环, 如果是windows系统则会报错ConnectionResetError
, 这是因为上边的server code代码中, conn对象是一个服务端和客户端的双向数据通道, 当客户端强行关闭之后, 就会出现报错导致服务端不可用了
- 这个bug在linux上处理起来就是在
data=conn.recv(1024)
加一个判断是否为空就可以了
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8081))
phone.listen(5)
print('starting...')
conn,client_addr=phone.accept()
print(client_addr)
while True:
# print(phone)
# print(conn)
# print(client_addr)
data=conn.recv(1024)
if not data:break
print('客户端数据',data.decode('UTF-8'))
conn.send(data.upper())
conn.close()
phone.close()
- 这个bug在windows上处理起来就是在
data=conn.recv(1024)
加一个try...except就可以了
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8081))
phone.listen(5)
print('starting...')
conn,client_addr=phone.accept()
print(client_addr)
while True:
# print(phone)
# print(conn)
# print(client_addr)
try:
data=conn.recv(1024)
print('客户端数据',data.decode('UTF-8'))
conn.send(data.upper())
except ConnectionResetError:
break
conn.close()
phone.close()
上述client code代码有一个bug, 就是直接敲一个回车的时候, 客户端会卡主. 原因是当敲完回车之后, 代码会走到phone.send
这一行, 这一行代码会给操作系统发一个空, 操作系统认为没有数据, 所以并不会发送给server端, 所以代码会一直停留在phone.recv
这个位置等待接收数据, 这个bug处理起来也很简单, 同样加一个判断msg
是否为空就可以了
client code fix bug
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8081))
while True:
msg=input('>> ')
if not msg:continue
phone.send(msg.encode('utf-8'))
data=phone.recv(1024)
print(data)
phone.close()
服务端可以连续接收请求版
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1',8081))
phone.listen(5)
while True:
print('starting...')
conn, client_addr = phone.accept()
print(client_addr)
while True:
# print(phone)
# print(conn)
# print(client_addr)
try:
data=conn.recv(1024)
print('客户端数据',data.decode('UTF-8'))
conn.send(data.upper())
except ConnectionResetError:
break
conn.close()
phone.close()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8081))
while True:
msg=input('>> ')
if not msg:continue
phone.send(msg.encode('utf-8'))
data=phone.recv(1024)
print(data)
phone.close()
模拟ssh远程执行命令
server code
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket,subprocess
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('127.0.0.1',8081))
phone.listen(5)
while True:
print('starting...')
conn, client_addr = phone.accept()
print(client_addr)
while True:
# print(phone)
# print(conn)
# print(client_addr)
try:
cmd=conn.recv(1024)
res = subprocess.Popen(cmd.decode('gbk'), shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout=res.stdout.read()
stderr=res.stderr.read()
data=stdout+stderr
conn.send(data)
except ConnectionResetError:
break
conn.close()
phone.close()
client code
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8081))
while True:
cmd=input('>> ')
if not cmd:continue
phone.send(cmd.encode('gbk'))
data=phone.recv(1024)
print(data.decode('gbk'))
phone.close()
解决粘包问题
引入struct模块
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import struct
res=struct.pack('i',111111)
print(res,type(res),len(res)) #len(res)永远是4, 所以在客户端就可以先收4个字节来判断全部数据的字节大小
obj=struct.unpack('i',res)
print(obj[0])
server code
简单版
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket,subprocess
import struct
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(('127.0.0.1',8081))
phone.listen(5)
while True:
print('starting...')
conn, client_addr = phone.accept()
print(client_addr)
while True:
# print(phone)
# print(conn)
# print(client_addr)
try:
cmd=conn.recv(1024)
res = subprocess.Popen(cmd.decode('gbk'), shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout=res.stdout.read()
stderr=res.stderr.read()
data=stdout+stderr
header=struct.pack('i',len(data))
conn.send(header)
conn.send(stdout)
conn.send(stderr)
except ConnectionResetError:
break
conn.close()
client code
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import struct
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8081))
while True:
cmd=input('>> ')
if not cmd:continue
phone.send(cmd.encode('gbk'))
obj = phone.recv(4)
total_size = struct.unpack('i',obj)[0]
# print(total_size)
recv_size=0
recv_data=b''
while recv_size < total_size:
res=phone.recv(1024)
recv_data+=res
recv_size+=len(res)
print(recv_data.decode('gbk'))
phone.close()