python之socket编程

2019-02-18  本文已影响0人  ivan_cq

服务端
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()

客户端
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服务

上一篇下一篇

猜你喜欢

热点阅读