- 实例一:最简单的socket例子
这个程序,实现了客户端向服务端发送数据,服务端将小写字母变为大写并且返回
服务端
import socket
server=socket.socket() #默认ipv4 tcp/ip 相当于声明socket类型同时生成socket连接对象 既定义了地址簇,又定义了协议类型
server.bind(('localhost',1010) ) #绑定要监听的端口,只接受一个参数,是一个元组
server.listen() #开始监听
print('我要开始等电话了!') #但是这个地方还没有真正开始等,只是做好了准备工作
conn,addr=server.accept() #等电话打进来,真正的开始等电话打进来
print(conn,addr) #conn就是客户端连过来而在服务器端为其生成的一个连接实例,也就是标记,后面就是对方的地址
print("电话来了!")
data=conn.recv(1024) #使用实例接受,发送
print(data)
conn.send(data.upper()) #发过去变成大写
server.close() #关闭手机 所以是server
# server.accept()
# data=server.recv(1024)
# print('recv ',data)
# server.send(data.upper())
# server.close()
#TypeError: a bytes-like object is required, not 'str'
#不能直接使用server去接听 server.accept
#这里就需要想手机切换通话,只是一根电话线,让别的人通过这一根电话线打进来切换接听另一个人
#所以用该给每个人标记一下 conn,addr=server.accept() 返回第一个是连接的标记位,第二个是对方的地址
结果:
F:\anaconda\python.exe F:/web/s14/网络编程、socket编程/socket_server.py
我要开始等电话了!
<socket.socket fd=272, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 1010), raddr=('127.0.0.1', 49866)> ('127.0.0.1', 49866)
电话来了!
b'hello world!'
客户端
import socket
client=socket.socket() #默认ipv4 tcp/ip 相当于声明socket类型同时生成socket连接对象
client.connect(('localhost',1010))
client.send(b"hello world!") # 不加b会出现这个错误 : TypeError: a bytes-like object is required, not 'str' 在python2里面可以发字符串、字节bytes
#但是在python里只能发比特流的bytes类型
data=client.recv(1024) #收1024字节的数据 1kb
print(data)
client.close()
结果:
F:\anaconda\python.exe F:/web/s14/网络编程、socket编程/socket_client.py
b'HELLO WORLD!'
客户端
import socket
client=socket.socket()
client.connect(('localhost',1010))
while True:
msg=input('>>:').strip()
if len(msg) == 0:continue
client.send(msg.encode("utf-8"))
data=client.recv(1024)
print(data.decode())
client.close()
服务端
import socket
server=socket.socket()
server.bind(('localhost',1010) )
server.listen(5)
while True: #如果没有这个while循环那么一旦客户端关闭连接,在linux、mac系统上,服务端一直收的都是空,陷入一个死循环。而在windows上就会报错。
conn,addr=server.accept() #必须放在外面,如果放在里面,可以同时接两个电话,但是只能说一句
while True:
data=conn.recv(1024)
if not data:
print("client lost!")
break
print(data.decode())
conn.send(data.upper())
server.close()
- 实例三:socket实现简单ssh功能(处理大数据)
客户端
import socket
client=socket.socket()
client.connect(('localhost',9999))
while True:
cmd = input(">>:").strip()
if len(cmd) == 0:continue
client.send(cmd.encode('utf-8'))
cmd_res_size=client.recv(1024) #接受命令返回结果的长度
print("命令长度: ",cmd_res_size)
recv_data = b''
recv_size = 0
while recv_size < int(cmd_res_size.decode()):
data=client.recv(1024)
recv_size += len(data) #每次收到的结果很可能小于1024 所以这里必须用len判断
print(recv_size)
recv_data+=data
else:
print("cmd res recive done!",recv_size)
print(recv_data.decode())
client.close()
服务端
import socket
import os
server=socket.socket()
server.bind(('localhost',9999))
server.listen()
while True:
conn,addr=server.accept()
while True:
print("等待新指令")
data=conn.recv(1024)
if not data:
print("客户端已断开!")
break
print("执行指令:",data)
cmd_res=os.popen(data.decode()).read() #接受字符串,执行结果也是字符串
if len(cmd_res) == 0:
cmd_res='cmd has no output!'
#conn.send(str(len(cmd_res)).encode('utf-8'))
conn.send(str(len(cmd_res.encode())).encode("utf-8")) # 整数不能直接encode得先str 先把大小发给客户端
conn.send(cmd_res.encode('utf-8'))
server.close()
服务端
import socket
import os,hashlib
server=socket.socket()
server.bind(('localhost',9999))
server.listen()
while True:
conn,addr=server.accept()
while True:
print("等待新指令")
data=conn.recv(1024)
if not data:
print("客户端已断开!")
break
cmd,filename=data.decode().split()
if os.path.isfile(filename):
f=open(filename,'rb')
m=hashlib.md5()
file_size=os.stat(filename).st_size
conn.send(str(file_size).encode('utf-8')) #发送文件大小
conn.recv(1024) #wait for ack
for line in f:
m.update(line)
conn.send(line)
f.close()
conn.send(m.hexdigest().encode()) #send md5
print(m.hexdigest())
print('send done!')
server.close()
客户端
import socket,hashlib
client=socket.socket()
client.connect(('localhost',9999))
while True:
cmd = input(">>:").strip()
if len(cmd) == 0:continue
if cmd.startswith("get"):
client.send(cmd.encode())
server_response=client.recv(1024)
print("文件大小",server_response)
client.send("ready to recv file".encode()) #ack
file_total_size = int(server_response.decode())
rece_size=0
filename=cmd.split()[1]
f=open(filename + '.new',"wb")
m=hashlib.md5()
while rece_size < file_total_size: #解决了粘包,有可能大于,就把MD5粘过来了
if file_total_size-rece_size>1024: #代表要收不止一次
size=1024
else: #最后一次,剩多少,收多少
size=file_total_size-rece_size
data=client.recv(size)
rece_size +=len(data)
m.update(data)
f.write(data)
else:
new_file_md5=m.hexdigest()
print(rece_size,file_total_size)
f.close()
server_file_md5 = client.recv(1024)
print("server file md5", server_file_md5.decode())
print("client file md5", new_file_md5)
client.close()
md5校验
import hashlib
m=hashlib.md5()
m.update(b"test")
m.update(b'abc')
print(m.hexdigest())
m2=hashlib.md5()
m2.update(b'testabc')
print(m2.hexdigest())
#证明了逐行 md5 和一起md5的效果是一样的
服务端
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self): #默认在父类里是空的,客户端所有的交互都是在handle里完成的
while True:
try:
self.data=self.request.recv(1024).strip() #ConnectionResetError
print("{} wrote: ".format(self.client_address[0])) #打印客户端的ip地址
print(self.data)
# if not self.data: #代表客户端断开
# print(self.client_address,"断开了")
# break #在使用socket时候,windows上关闭客户端会报错,linux'会陷入无限循环而不报错
#所以 需判断
#而在socketserver上widows和linnux上断开客户端都会报ConnectionResetError
#所以使用异常处理
self.request.send(self.data.upper())
except ConnectionResetError as e:
print("err",e)
break
#每一个客户端的请求过来都会实例化我们新创建的类
if __name__ == '__main__':
HOST,PORT = 'localhost', 6969
# server=socketserver.TCPServer((HOST,PORT),MyTCPHandler)
server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler) #多并发
server.serve_forever()
项目:实现ftp服务
网友评论