Python之socket

 

Socket通长也称作"套接字",用于描述IP地址和端口,是一个通信的句柄.

vim day8-16.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/usr/bin/env python
#coding:utf-8
import socket
 
def handle_request(client):
    buf = client.recv(1024)
    print buf
    client.send("HTTP/1.1 200 OK\r\n\r\n")
    client.send("Hello, World")
 
def main():
    #创建socket对象
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    #bind方法监听某个端口
    sock.bind(('127.0.0.1',8080))
    #开始监听,
    sock.listen(5)
 
    while True:
        #阻塞,等...
        #直到有请求连接
        connection, address = sock.accept()
        #connection代表客户端sockert对象
        #address客户端IP地址
        handle_request(connection)
        connection.close()
 
if __name__ == '__main__':
  main()

运行,然后在开启一个客户端访问

本客户端返回

 

使用python建立一个socket的服务端和客户端

vim socket_server.py        

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python
#coding:utf-8
 
 
import socket
 
obj_server = socket.socket()
obj_server.bind(('localhost',8341))
obj_server.listen(5)                    #开始监听最大连接数5
while True:
    print 'waiting...'
    conn,addr = obj_server.accept()
    client_data =  conn.recv(1024)                      #最多一次性接收1024size
    print client_data
    conn.send('好的')
    conn.close()
                  

vim  socket_client.py

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python
#coding:utf-8
 
import socket
 
 
obj = socket.socket()
obj.connect(('localhost',8341))
obj.send('我爱北京天安门')
server_data = obj.recv(1024)
print server_data
obj.close()
~               

运行服务端,然后新开一个窗口运行客户端

 

智能机器人实例

vim day8-18.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
import socket
 
ip_port = ('127.0.0.1',8888)
sk = socket.socket()
sk.bind(ip_port)
sk.listen(5)
 
while True:
    conn,address = sk.accept()
    conn.sendall('欢迎致电10086,请输入1xxx,0转人工服务')
    Flag = True
    while Flag:
        data = conn.recv(1024)                  #阻塞等待客户端发生数据
        print data                              #打印从客户端接收到的数据
        if data == 'exit':
            Flag = False
        elif data == '0':
            conn.sendall('您的通话可能被录音')
        else:
            conn.sendall('请重新输入')
    conn.close()

vim day8-19.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
import socket
 
ip_port = ('127.0.0.1',8888)
sk = socket.socket()
sk.connect(ip_port)                     #客户端连接服务端
sk.settimeout(5)
 
while True:
    data = sk.recv(1024)                #接收服务端数据欢迎致电...
    print 'recevie:',data
    inp = raw_input('please input:')
    sk.sendall(inp)
    if inp == 'exit':
        break
 
sk.close()

执行过程

服务端

客户端

PS:一个socket同时只能处理一个请求,如果一个请求在连接中,其他请求在过来将排队等待,等待时间为设置的超时时间为5s,python提供了一个模块用于多线程模块socketserver

 

SoketServer

多线程条件

1,必须写一个类

2,必须继承SocketServer.BaseRequestHandler

3,必须写一个方法而且方法名必须为handle

4,必须调用ThreadingTCPServer方法来实现多线程

day8-22.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import SocketServer
import os
class MyServer(SocketServer.BaseRequestHandler):
 
    def handle(self):
        print "--got connection from", self.client_address
        while True:
            data = self.request.recv(1024)
            print "Recv from cmd:%s" %(data)
            cmd_res = os.popen(data).read()
            print 'cmd_res:',len(cmd_res)       #打印服务器发送数据长度
            self.request.sendall(cmd_res)
 
if __name__ == '__main__':
    server = SocketServer.ThreadingTCPServer(('127.0.0.1',8009),MyServer)
    server.serve_forever()                              #永久运行

客户端vim day8-23.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
import socket
 
 
ip_port = ('127.0.0.1',8009)
sk = socket.socket()
sk.connect(ip_port)
sk.settimeout(5)
 
while True:
#    data = sk.recv(1024)
#    print 'receive:',data
    inp = raw_input('please input:')
    sk.sendall(inp)
    while True:
        data = sk.recv(1024)
        print "---data---"
#       if len(data) == 0:
        if len(data) < 1024:
            print '---not data---'
            break
        print data
    if inp == 'exit':
        break
 
sk.close()

客户端输入命令服务端把命令结果返回给客户端打印

 

修改代码让服务器在发送数据之前就把要发送的大小发送给客户端,客户端根据包的大小进行判断打印

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import SocketServer
import os
class MyServer(SocketServer.BaseRequestHandler):
 
    def handle(self):
        print "--got connection from", self.client_address
        while True:
            data = self.request.recv(1024)
            print "Recv from cmd:%s" %(data)   
            cmd_res = os.popen(data).read()
        print 'cmd_res:',len(cmd_res)   #打印服务器发送数据长度
            self.request.send( str(len(cmd_res)) ) #服务端要给客户端发多长数据
        self.request.sendall(cmd_res)
 
if __name__ == '__main__':
    server = SocketServer.ThreadingTCPServer(('127.0.0.1',8009),MyServer)
    server.serve_forever()              #永久运行

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
import socket
 
 
ip_port = ('127.0.0.1',8009)
sk = socket.socket()
sk.connect(ip_port)
sk.settimeout(5)
 
while True:
#    data = sk.recv(1024)
#    print 'receive:',data
    inp = raw_input('please input:')
    sk.sendall(inp)
    res_size = sk.recv(1024)
    print "goint to recv data size:",res_size,type(res_size)#打印将收到多少数据和数据类型
     
    total_size = int(res_size)                  #共要收取的
    received_size = 0
    while True:
    data = sk.recv(1024)
    received_size += len(data)
    print "---data---"
#   if len(data) == 0:
#   if len(data) < 1024:
    if total_size == received_size:         #如果收到的大小等于收到的大小代表收完了
        print data
        print '---not data---'
        break
        print data
    if inp == 'exit':
        break
 
sk.close()

PS:这样也会出现问题,这两个包可能在网络层集合成一个包发送给客户端导致客户端接收ValueError,这种现象叫连包,可以通过修改服务器端代码(比如两个包之间sleep1秒再发送下一个包),但是效率太低

可以通过在两条消息直接加代码解决

服务端

 客户端回一条可以是一个空格

 

作业:客户端往服务端发文件,客户端可以从服务端下载文件,实现文件MD5验证和用户验证

posted @   minseo  阅读(311)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示