zoukankan      html  css  js  c++  java
  • socket基础篇

    server_scoket.py

    #!/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("33[1;31;0m客户端未发送数据!33[0m")
                        break
                    print("接收数据,客户端%d:33[1;31;0m%s33[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("33[1;31;0m客户端%d关闭连接!33[0m"%cid)
                    break
        except KeyboardInterrupt as e:
            print(e)
            break
        conn.close()
    

    client.py

    #!/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("发送数据: 33[1;32;0m%s33[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("33[1;32;0m%s33[0m"%str(server_result,"gbk"),end="")
        # try:
        #     print("接收数据: 33[1;32;0m%s33[0m"%str(server_reply,'utf-8'))
        # except UnicodeDecodeError:
        #     print("接收数据: 33[1;32;0m%s33[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()会阻塞:

    红框的包是以前的。

  • 相关阅读:
    Android开发探秘之一:创建可以点击的Button
    TCP之心跳包实现思路
    Asp.net与Dojo交互:仪器仪表实现
    Asp.net Json数据解析的一种思路
    Asp.net通过Jquery操作WebService进行Ajax读写
    GridView自定义删除操作
    从客户端中检测到有潜在危险的request.form值
    JUC-Condition线程通信
    ModelAndView 配置与使用
    SpringMVC之ModelAndView的用法(转)
  • 原文地址:https://www.cnblogs.com/owasp/p/5534259.html
Copyright © 2011-2022 走看看