socket基礎篇

server_scoket.pypython

#!/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.pylinux

#!/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:

一、在windowns上用tskill pid時,windowns會發生rst包,且服務端if not data沒法抓到,而是在
except ConnectionResetError as e:
                print(e)
捕捉到了。

二、windows 上Ctrl + C ,linus上 kill  pid、kill -9 pid 、Ctrl + c,客戶端會發送fin來進行正常的結束會話shell

 

三、阻塞數據庫

開啓多個客戶端會發生阻塞,可是正常的tcp三次握手能夠正常鏈接,只是發生過去的數據服務器會迴應空數據的包。windows

及時我在客戶端加了if not data: 也是沒用的 ,應爲若是recv()收到ack應該是會阻塞的(不肯定,多是這樣)服務器

客戶端仍是卡住:socket

,且客戶端和服務器端也沒有數據傳輸。tcp

某一個客戶端結束會話後,這個客戶端會立刻收到服務器端的數據。spa

服務器端的recv()收到ack,recv()會阻塞。3d

 

四、客戶端鏈接超過監聽設置數。sk.listen(2),表示能夠掛起兩個。

第一個client在linux,而後再windows開了三個客戶端,均可以連上(很奇怪),當在windows開啓第四個client時,出現問題,以下:

 這裏服務器端的那個端口爲14378的鏈接已經斷開。14378的客戶端再發生數據庫以下:

 

客戶端一個一個斷開後,掛起的客戶端收到服務器的數據,客戶端的recv()一個個被"激活"。

可是當server起在windows時,確實只能掛起兩個:

爲了抓包,第四個客戶端在linux發起:

 

五、當發送數據爲空或回車時,send()會阻塞:

紅框的包是之前的。

相關文章
相關標籤/搜索