socket基础篇

server_scoket.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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/usr/bin/env python3.5
# -*- coding:utf-8 -*-
import socket
import subprocess
 
 
ip_port = ('0.0.0.0',9999)
 
sk = socket.socket()
sk.bind(ip_port)
sk.listen(2)
 
cid = 0
 
while True:
    cid += 1
    print('server waiting...')
    try:
        conn,addr = sk.accept()
        # client_data = conn.recv(1024)
        # print(str(client_data,'utf8'))
        # conn.sendall(bytes('不要回答,不要回答,不要回答','utf8'))
        while True:
            try:
                client_data = conn.recv(8192)
                str_clinet_data = str(client_data,'utf8').strip()
 
                if not client_data.decode():
                    print("\033[1;31;0m客户端未发送数据!\033[0m")
                    break
                print("接收数据,客户端%d:\033[1;31;0m%s\033[0m"%(cid,str_clinet_data))
                cmd_data = subprocess.Popen(str_clinet_data,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
                cmd_data_out , cmd_error =  cmd_data.communicate()   # 返回bytes
                # if cmd_error != bytes("","utf-8"):
                if cmd_error:
                    cmd_data_result = cmd_error
                else:
                    cmd_data_result = cmd_data_out
                try:
                    print(str(cmd_data_result,"gbk"))
                except UnicodeDecodeError:
                    print(str(cmd_data_result,"utf-8"))
                # conn.send(client_data)
                cmd_result_size = b"CMD_RESULT_SIZE|%d"%len(cmd_data_result)
                # print(cmd_result_size)
                conn.send(cmd_result_size)
 
                client_ack = conn.recv(20)
                if client_ack == b"CMD_RESULT_SIZE_OK":
                    print("收到客户端的确认,开始发送数据!")
                    conn.send(cmd_data_result)
            except ConnectionResetError as e:
                print(e)
                print("\033[1;31;0m客户端%d关闭连接!\033[0m"%cid)
                break
    except KeyboardInterrupt as e:
        print(e)
        break
    conn.close()

client.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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
ip_port = ('192.168.5.124',9999)
 
sk = socket.socket()
sk.connect(ip_port)
 
# sk.sendall(bytes('请求占领地球','utf8'))
# server_reply = sk.recv(1024)
# print(str(server_reply,'utf8'))
 
while True:
    try:
        user_input = input("cmd>>:").strip()
    except KeyboardInterrupt as e:
        print(e)
        break
    if user_input == "":
        continue
    if user_input == 'q':
        break
 
    sk.send(bytes(user_input,'utf8'))
    # print("发送数据: \033[1;32;0m%s\033[0m"%user_input)
 
    server_reply_size_data = sk.recv(50)
    # print(server_reply_size_data)
    server_reply_size_flag, server_reply_size = server_reply_size_data.decode("utf-8").split("|")
    server_reply_size = int(server_reply_size)
    if server_reply_size_flag == "CMD_RESULT_SIZE":
        print("服务端将发送字节数:%d"%server_reply_size)
        print("给服务端发送确认!")
        sk.send(b"CMD_RESULT_SIZE_OK")
    server_result = b""
    recv_size = 0
    # n = 1
    while recv_size < server_reply_size:
        server_reply = sk.recv(500)
        server_result += server_reply
        recv_size += len(server_reply)
        print("共接收%d字节"%recv_size)
        # code,server_result = str(server_reply[:9].split(b'0')[0],"utf-8"),server_reply[9:]
    else:
        print("------load-done-----")
        print("\033[1;32;0m%s\033[0m"%str(server_result,"gbk"),end="")
    # try:
    #     print("接收数据: \033[1;32;0m%s\033[0m"%str(server_reply,'utf-8'))
    # except UnicodeDecodeError:
    #     print("接收数据: \033[1;32;0m%s\033[0m"%str(server_reply,'gbk'))
 
sk.close()

环境:server运行在linux,client运行在linux和windows:

1、在windowns上用tskill pid时,windowns会发生rst包,且服务端if not data无法抓到,而是在
except ConnectionResetError as e:
                print(e)
捕捉到了。

2、windows 上Ctrl + C ,linus上 kill  pid、kill -9 pid 、Ctrl + c,客户端会发送fin来进行正常的结束会话

 

3、阻塞

开启多个客户端会发生阻塞,但是正常的tcp三次握手可以正常连接,只是发生过去的数据服务器会回应空数据的包。

及时我在客户端加了if not data: 也是没用的 ,应为如果recv()收到ack应该是会阻塞的(不确定,可能是这样)

客户端还是卡住:

,且客户端和服务器端也没有数据传输。

某一个客户端结束会话后,这个客户端会马上收到服务器端的数据。

服务器端的recv()收到ack,recv()会阻塞。

 

4、客户端连接超过监听设置数。sk.listen(2),表示可以挂起两个。

第一个client在linux,然后再windows开了三个客户端,都可以连上(很奇怪),当在windows开启第四个client时,出现问题,如下:

 这里服务器端的那个端口为14378的连接已经断开。14378的客户端再发生数据库如下:

 

客户端一个一个断开后,挂起的客户端收到服务器的数据,客户端的recv()一个个被"激活"。

但是当server起在windows时,确实只能挂起两个:

为了抓包,第四个客户端在linux发起:

 

5、当发送数据为空或回车时,send()会阻塞:

红框的包是以前的。

posted @   电神  阅读(390)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示