一、socket模块
socket模块提供了底层的接口,通过socket模块可以实现不同计算机的通信
ip+port定位了计算机中应用程序的具体位置,socket绑定ip+port来建立链接,socket的方法详情:
socket(family, type, proto): socket函数创建一个socket对象,使用socket对象创建连接,
family协议族,默认AF_INET,ipv4协议,type,socket类型,proto协议类型
bind((ip, port)): 绑定服务器地址
listen(n): 监听socket创建的链接, n代表指定连接队列数,
connect(('127.0.0.1', 8080)): 连接到服务端
accept():等待客户端连接,返回连接对象和客户端ip组成的元组
recv(n): 接收数据,n代表接受固定的数据
send(data): 发送数据
例子:模拟客户端服务端通信
server:
#!/usr/bin/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, addr = phone.accept()
print(conn)
print('client addr: ', addr)
print('ready to read msg')
client_msg = conn.recv(1024)
print('client msg: %s' %(client_msg))
conn.send(client_msg.upper())
conn.close()
phone.close()
client
#!/usr/bin/pytthon
# --*-- coding: utf-8 --*--
import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8080))
phone.send('hello'.encode('utf-8'))
back_msg = phone.recv(1024)
print(back_msg.decode('gbk'))
phone.close()
模拟循环发送接收数据
server
import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.bind(('127.0.0.1', 8080))
phone.listen(5)
while True:
print('starting...')
conn, addr = phone.accept()
print('client addr ', addr)
while True:
try:
client_msg = conn.recv(1024)
if not client_msg: break
print('client_msg: %s' %client_msg)
conn.send(client_msg.upper())
except Exception:
break
conn.close()
phone.close()
client
import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8080))
while True:
msg = input(">>: ")
if not msg: continue
phone.send(msg.encode('utf-8'))
back_msg = phone.recv(1024)
print(back_msg.decode('utf-8'))
phone.close()
模拟远程执行命令,并返回结果
server
import socket
import subprocess
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.bind(('127.0.0.1', 8080))
phone.listen(5)
while True:
print('starting...')
conn,addr = phone.accept()
print('client addr: ', addr)
while True:
try:
cmd = conn.recv(1024)
if not cmd: break
res = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
err = res.stderr.read()
if err:
cmd_res = err
else:
cmd_res = res.stdout.read()
conn.send(cmd_res)
except Exception:
break
conn.close()
phone.close()
client
import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8080))
while True:
cmd = input('>>: ').strip()
if not cmd: continue
phone.send(cmd.encode('utf-8'))
back_msg = phone.recv(1024)
print(back_msg.decode('gbk'))
phone.close()
粘包现象,数据包无规则断开,出现不希望的断开现象
server
from socket import *
import time
tcp_server = socket(AF_INET, SOCK_STREAM)
tcp_server.bind(('127.0.0.1', 8080))
tcp_server.listen(5)
conn, addr = tcp_server.accept()
res1 = conn.recv(5)
res2 = conn.recv(5)
res3 = conn.recv(7)
print(res1.decode('gbk'))
print(res2.decode('gbk'))
print(res3.decode('gbk'))
client
from socket import *
import time
tcp_client = socket(AF_INET, SOCK_STREAM)
tcp_client.connect(('127.0.0.1', 8080))
tcp_client.send('hello world'.encode('utf-8'))
time.sleep(5)
tcp_client.send('egon666'.encode('utf-8'))
解决粘包问题,使用struct模块,打包数据并解包数据
例子:
server
import socket
import subprocess
import struct
import json
phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.bind(('127.0.0.1', 8080))
phone.listen(5)
while True:
print('starting...')
conn, addr = phone.accept()
print('client addr: ', addr)
while True:
try:
cmd = conn.recv(1024)
if not cmd:break
res = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
err = res.stderr.read()
if err:
cmd_res = err
else:
cmd_res = res.stdout.read()
head_dict = {'filename': None, 'hash': None, 'total_size': len(cmd_res)}
head_json = json.dumps(head_dict)
head_bytes = head_json.encode('utf-8')
print(struct.pack('i', len(head_bytes)))
conn.send(struct.pack('i', len(head_bytes)))
conn.send(head_bytes)
conn.send(cmd_res)
except Exception:
break
conn.close()
phone.close()
client
import socket
import struct
import json
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8080))
while True:
cmd = input('>>: ').strip()
if not cmd: continue
phone.send(cmd.encode('utf-8'))
head_struct = phone.recv(4)
#print(head_struct)
head_len = struct.unpack('i', head_struct)[0]
head_bytes = phone.recv(head_len)
head_json = head_bytes.decode('utf-8')
#print(head_json)
head_dict = json.loads(head_json)
#print(head_dict)
total_size = head_dict['total_size']
recv_size = 0
data = b''
while recv_size < total_size:
recv_data = phone.recv(1024)
data += recv_data
recv_size += len(recv_data)
print(data.decode('gbk'))
phone.close()
本文出自 “linux技术” 博客,请务必保留此出处http://haoyonghui.blog.51cto.com/4278020/1939996