zoukankan      html  css  js  c++  java
  • Python开发【第八篇】:socket网络编程

    服务端:

    1. import socket
    2. server = socket.socket()
    3. #绑定要监听的端口
    4. server.bind(('localhost',6969))
    5. #监听
    6. server.listen()
    7. print("等待连接...")
    8. #等待连接,conn就是客户端连过来在服务端为其生成的一个连接实例
    9. conn,addr = server.accept()
    10. print("连接进行中...")
    11. print(conn,addr)
    12.  
    13. data = conn.recv(1024)
    14. print("recv:",data)
    15. conn.send(data.upper())
    16. server.close()

    客户端:

    1. import socket
    2.  
    3. #声明socket类型,同时生产socket连接对象
    4. client = socket.socket()
    5. client.connect(('localhost',6969))
    6. client.send(b"hello world!")
    7. data = client.recv(1024)
    8. print("recv:",data)
    9. client.close()

    服务端输出:

    1. 等待连接...
    2. 连接进行中...
    3. <socket.socket fd=328, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 6969), raddr=('127.0.0.1', 50248)> ('127.0.0.1', 50248)
    4. recv: b'hello world!'

    客户端输出:

    1. recv: b'HELLO WORLD!'

    连续发送信息:

    服务端:

    1. import socket
    2. client = socket.socket()
    3. client.connect(('localhost',6969))
    4. while True:
    5.     msg = input(">>:").strip()
    6.     client.send(msg.encode("utf-8"))
    7.     data = client.recv(1024)
    8.     print("recv:",data.decode())
    9. client.close()

    客户端:

    1. import socket
    2.  
    3. #声明socket类型,同时生产socket连接对象
    4. client = socket.socket()
    5. client.connect(('localhost',6969))
    6. client.send(b"hello world!")
    7. # client.send("我要下载".encode("utf-8"))
    8. data = client.recv(1024)
    9. print("recv:",data)
    10. client.close()

    在linux上客户端执行命令

    服务端:

    1. [root@test-c2c-console01 oldboy]# cat socket_server.py
    2. #-*-coding:utf-8-*-
    3. #_author_="golden"
    4. #服务端
    5. import socket
    6. import os
    7.  
    8. server = socket.socket()
    9. #绑定要监听的端口
    10. server.bind(('localhost',6969))
    11. #监听,最大连接数
    12. server.listen(5)
    13. print("等待连接...")
    14. while True:
    15.     #conn就是客户端连过来在服务端为其生成的一个连接实例
    16.     conn,addr = server.accept()
    17.     print("连接进行中...")
    18.     print(conn,addr)
    19.     while True:
    20.         data = conn.recv(1024)
    21.         print("recv:",data)
    22.         if not data:
    23.             print("客户端断开!")
    24.             break
    25.         res = os.popen(data).read()
    26.         conn.send(res)
    27. server.close()

    客户端:

    1. [root@test-c2c-console01 oldboy]# cat socket_client.py
    2. #-*-coding:utf-8-*-
    3. _author_ = "golden"
    4. #客户端
    5. import socket
    6. #声明socket类型,同时生成socket连接对象
    7. client = socket.socket()
    8. client.connect(('localhost',6969))
    9. while True:
    10.     msg = raw_input(">>:").strip()
    11.     if len(msg) == 0:continue
    12.     client.send(msg.encode("utf-8"))
    13.     data = client.recv(102400)
    14.     print(data.decode())
    15.  
    16. client.close()

    linux发送文件

    服务端:

    1. [root@test-c2c-console01 oldboy]# cat socket_server.py
    2. #-*-coding:utf-8-*-
    3. #_author_="golden"
    4. #服务端
    5. import socket
    6. import os
    7.  
    8. server = socket.socket()
    9. #绑定要监听的端口
    10. server.bind(('localhost',6969))
    11. #监听,最大连接数
    12. server.listen(5)
    13. print("等待连接...")
    14. while True:
    15.     #conn就是客户端连过来在服务端为其生成的一个连接实例
    16.     conn,addr = server.accept()
    17.     print("连接进行中...")
    18.     print(conn,addr)
    19.     while True:
    20.         data = conn.recv(1024)
    21.         print("recv:",data)
    22.         if not data:
    23.             print("客户端断开!")
    24.             break
    25.         #res = os.popen(data).read()
    26.         #conn.send(res)
    27.         f = open("move.mkv")
    28.         data = f.read()
    29.         conn.send(data)
    30. server.close()

    客户端:

    1. [root@test-c2c-console01 oldboy]# cat socket_client.py
    2. #-*-coding:utf-8-*-
    3. _author_ = "golden"
    4. #客户端
    5. import socket
    6. #声明socket类型,同时生成socket连接对象
    7. client = socket.socket()
    8. client.connect(('localhost',6969))
    9. while True:
    10.     msg = raw_input(">>:").strip()
    11.     if len(msg) == 0:continue
    12.     client.send(msg.encode("utf-8"))
    13.     data = client.recv(102400)
    14.     #print(data.decode())
    15.     f = open("video.avi",'wb')
    16.     f.write(data)
    17.     f.close()
    18.  
    19. client.close()

    一次最多发送的数据量32768(不同系统有区别)

    1. [root@test-c2c-console01 oldboy]# ll *.avi *.mkv
    2. -rw-r--r-- 1 root root 681790584 Dec 27 19:26 move.mkv
    3. -rw-r--r-- 1 root root 32768 Feb 12 08:47 video.avi

    多次发送

    服务端:

    1. [root@test-c2c-console01 oldboy]# cat socket_server.py
    2. #-*-coding:utf-8-*-
    3. #_author_="golden"
    4. #服务端
    5. import socket
    6. import os
    7.  
    8. server = socket.socket() #实例化一个socket
    9. #绑定要监听的端口
    10. server.bind(('localhost',6969))
    11. #监听,最大连接数
    12. server.listen(5)
    13. print("等待连接...")
    14. while True:
    15.     #conn就是客户端连过来在服务端为其生成的一个连接实例
    16.     conn,addr = server.accept()
    17.     print("连接进行中...")
    18.     print(conn,addr)
    19.     while True:
    20.         data = conn.recv(1024)
    21.         print("recv:",data)
    22.         if not data:
    23.             print("客户端断开!")
    24.             break
    25.         #res = os.popen(data).read()
    26.         #conn.send(res)
    27.         f = open("move.mkv")
    28.         data = f.read()
    29.         print(len(data))
    30.         conn.send(data)
    31. server.close()

    客户端:

    1. [root@test-c2c-console01 oldboy]# cat socket_client.py
    2. #-*-coding:utf-8-*-
    3. _author_ = "golden"
    4. #客户端
    5. import socket
    6. #声明socket类型,同时生成socket连接对象
    7. client = socket.socket()
    8. client.connect(('localhost',6969))
    9. f = open("video.avi",'wb')
    10. while True:
    11.     msg = raw_input(">>:").strip()
    12.     if len(msg) == 0:continue
    13.     client.send(msg.encode("utf-8"))
    14.     data = client.recv(102400)
    15.     #print(data.decode())
    16.     f.write(data)
    17.     f.flush()
    18.  
    19. client.close()

    每交互一次文件的变化:

    1. [root@test-c2c-console01 oldboy]# ll
    2. total 665832
    3. -rw-r--r-- 1 root root 681790584 Dec 27 19:26 move.mkv
    4. -rw-r--r-- 1 root root 0 Feb 12 09:08 video.avi
    5. [root@test-c2c-console01 oldboy]# ll
    6. total 665864
    7. -rw-r--r-- 1 root root 681790584 Dec 27 19:26 move.mkv
    8. -rw-r--r-- 1 root root 32768 Feb 12 09:08 video.avi
    9. [root@test-c2c-console01 oldboy]# ll
    10. total 665964
    11. -rw-r--r-- 1 root root 681790584 Dec 27 19:26 move.mkv
    12. -rw-r--r-- 1 root root 135168 Feb 12 09:08 video.avi
    13. [root@test-c2c-console01 oldboy]# ll
    14. total 666164
    15. -rw-r--r-- 1 root root 681790584 Dec 27 19:26 move.mkv
    16. -rw-r--r-- 1 root root 339968 Feb 12 09:09 video.avi
    17. [root@test-c2c-console01 oldboy]# ll
    18. total 666164
    19. -rw-r--r-- 1 root root 681790584 Dec 27 19:26 move.mkv
    20. -rw-r--r-- 1 root root 339968 Feb 12 09:09 video.avi

    socket实现简单的ssh

    服务端:

    1. import socket,os
    2. server = socket.socket()
    3. server.bind(('localhost',9999))
    4. server.listen()
    5. while True:
    6.     conn,addr = server.accept()
    7.     print("new conn:",addr)
    8.     while True:
    9.         data = conn.recv(1024)
    10.         if not data:
    11.             print("客户端已断开!")
    12.             break
    13.         print("执行指令:",data)
    14.         cmd_res = os.popen(data.decode()).read() #接收字符串,执行结果也是字符串
    15.         print("before send ",len(cmd_res))
    16.         if len(cmd_res) ==0:
    17.             cmd_res = "cmd has no output"
    18.         conn.send(str(len(cmd_res.encode())).encode("utf-8"))#先发大小给客户端
    19.         conn.send(cmd_res.encode("utf-8"))
    20.  
    21. server.close()

    客户端:

    1. import socket
    2. client = socket.socket()
    3. client.connect(('localhost',9999))
    4.  
    5. while True:
    6.     cmd = input(">>:").strip()
    7.     if len(cmd) == 0:continue
    8.     client.send(cmd.encode("utf-8"))
    9.     cmd_res_size = client.recv(1024)#接收大小
    10.     print("结果大小:",cmd_res_size)
    11.     received_size = 0
    12.     received_data = b''
    13.     while received_size < int(cmd_res_size.decode()):
    14.         data = client.recv(1024)
    15.         received_size += len(data) #每次收到的有可能小于1024,所以必须用len判断
    16.         # print(data.decode())
    17.         received_data += data
    18.     else:
    19.         print("cmd res receive done...",received_size)
    20.         print(received_data.decode())
    21.  
    22. client.close()

    注意socket粘包问题。

    方法一:在多个相连的send之间添加sleep。

    1. conn.send(str(len(cmd_res.encode())).encode("utf-8"))#先发大小给客户端
    2. time.sleep(0.5)
    3. conn.send(cmd_res.encode("utf-8"))

    方法二:在每次send之后进行一次交互。

    服务端:

    1. conn.send(str(len(cmd_res.encode())).encode("utf-8"))#先发大小给客户端client_ack = conn.recv(1024) #wait client to confirm
    2. print(client_ack.decode())
    3. conn.send(cmd_res.encode("utf-8"))

    客户端:

    1. cmd_res_size = client.recv(1024)#接收大小
    2. client.send("已准备好接收数据!".encode("utf-8"))

    socket实现简单的ftp

    ftp server:

    1、读取文件名

    2、检测文件是否存在

    3、打开文件

    4、检测文件大小

    5、发送文件大小给客户端

    6、等待客户端确认

    7、开始边读边发数据

    8、发送md5

    服务端:

    1. import socket,os,hashlib
    2. server = socket.socket()
    3. server.bind(("localhost",9999))
    4. server.listen()
    5. while True:
    6.     conn,addr = server.accept()
    7.     print("new conn:",addr)
    8.     while True:
    9.         print("等待指令...")
    10.         data = conn.recv(1024)
    11.         if not data:
    12.             print("客户端已断开!")
    13.             break
    14.         cmd,filename = data.decode().split()
    15.         print(filename)
    16.         if os.path.isfile(filename):
    17.             f = open(filename,"rb")
    18.             m = hashlib.md5()
    19.             file_size = os.stat(filename).st_size
    20.             conn.send(str(file_size).encode()) #send file size
    21.             conn.recv(1024) #wait for ack
    22.             for line in f:
    23.                 m.update(line)
    24.                 conn.send(line)
    25.             print("file md5",m.hexdigest())
    26.             f.close()
    27.             conn.send(m.hexdigest().encode()) #sed med5
    28.         print("send done")
    29.  
    30. server.close()

    客户端:

    1. import socket,hashlib
    2. client = socket.socket()
    3. client.connect(('localhost',9999))
    4. while True:
    5.     cmd = input(">>:").strip()
    6.     if len(cmd) == 0:continue
    7.     if cmd.startswith("get"):
    8.         client.send(cmd.encode())
    9.         server_response = client.recv(1024)
    10.         print("server_response:",server_response)
    11.         client.send(b"read to recv file")
    12.         file_total_size = int(server_response.decode())
    13.         received_size = 0
    14.         filename = cmd.split()[1]
    15.         f = open(filename + ".new","wb")
    16.         m = hashlib.md5()
    17.         while received_size < file_total_size:
    18.             if file_total_size - received_size > 1024:
    19.                 size = 1024
    20.             else:
    21.                 size = file_total_size - received_size
    22.  
    23.             data = client.recv(size)
    24.             received_size += len(data)
    25.             m.update(data)
    26.             f.write(data)
    27.             # print(file_total_size,received_size)
    28.         else:
    29.             new_file_md5 = m.hexdigest()
    30.             print("file recv done",received_size,file_total_size)
    31.             f.close()
    32.         server_file_md5 = client.recv(1024)
    33.         print("server file md5:{0},client file md5:{1}".format(server_file_md5,new_file_md5))
    34. client.close()

    SocketServer

    实现并发处理。

    The socketserver module simplifies the task of writing network servers.

    socketserver常用类型

    class socketserver.TCPServer(server_address,RequestHandlerClass,bind_and_activate=True)

    This uses the Internet TCP protocol,which provides for continuous streams of data between the client and server.

    class socketserver.UDPServer(server_address,RequestHandlerClass,bind_and_activate=True)

    This uses datagrams,which are discrete packets of information that may arrive out of order or be lost while in transit.The parameters are the same as for TCPServer.

    创建一个socketserver至少分一下几步:

    1、You mast create a request handler class by subclassing the BaseRequestHandler class and overriding its handle() method;this method will process incoming requests.

    创建一个请求处理类继承BaseRequestHandler,并且重写父类handle()。

    2、You mast instantiate one of the server classes,passing it the server's address and the request handler class.

    实例化TCPServer,并传递server ip和上述创建的请求处理类给这个TCPServer。

    3、Then call the handle_request() or server_forever() method of the server object to process one or many requests.

    server.handle_request():只处理一个请求

    server.server_forever():处理多个请求

    4、Call server_close() to close the socket.

    服务端:

    1. import socketserver
    2.  
    3. class MyTCPHandler(socketserver.BaseRequestHandler):
    4.  
    5.     def handle(self):
    6.         while True:
    7.             try:
    8.                 self.data = self.request.recv(1024).strip()
    9.                 print("{} wrote :".format(self.client_address[0]))
    10.                 print(self.data)
    11.                 self.request.send(self.data.upper())
    12.             except ConnectionResetError as CR:
    13.                 print("err",CR)
    14.                 break
    15.  
    16. if __name__ == "__main__":
    17.     HOST,PORT = "localhost",9999
    18.     # server = socketserver.TCPServer((HOST,PORT),MyTCPHandler) # 单线程
    19.     server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler) # 多线程,ForkingTCPServer多进程
    20.     server.serve_forever()

    客户端:

    1. import socket
    2.  
    3. client = socket.socket()
    4. client.connect(("localhost",9999))
    5. while True:
    6.     msg = input(">>:").strip()
    7.     if len(msg) == 0:continue
    8.     client.send(msg.encode("utf-8"))
    9.     data = client.recv(1024)
    10.     print("recv:",data.decode())
    11. client.close()

    开启一个新线程

    1. def process_request(self, request, client_address):
    2.     """Start a new thread to process the request."""
    3.     t = threading.Thread(target = self.process_request_thread,
    4.                          args = (request, client_address))
    5.     t.daemon = self.daemon_threads
    6.     t.start()

     

  • 相关阅读:
    基于kafka-net实现的可以长链接的消息生产者
    Windows服务安装、卸载、启动和关闭的管理器
    基于Confluent.Kafka实现的KafkaConsumer消费者类和KafkaProducer消息生产者类型
    [转]C#中HttpClient使用注意:预热与长连接
    基于Confluent.Kafka实现的Kafka客户端操作类使用详解
    [转载]RabbitMQ消息可靠性分析
    ASP.NET Core3.1 MVC 添加验证规则
    asp.net core 3.1 webapi接口参数有时间类型取不到值得问题
    asp.net core 3.1 引用的元包dll版本兼容性问题解决方案
    Python安装和环境配置
  • 原文地址:https://www.cnblogs.com/yinshoucheng-golden/p/6479331.html
Copyright © 2011-2022 走看看