簡體   English   中英

如何在 Python 中從同一個套接字發送和接收?

[英]How to send and receive from the same socket in Python?

我正在嘗試用 Python 編寫一個可以從同一個套接字發送和接收的客戶端程序,但它總是給我同樣的錯誤,哪個地址已經在使用中。 這是我正在嘗試編寫的函數。

def Login():
    username=raw_input()
    password=raw_input()
    message=raw_input()
    array=[username,password,message]

    TCP_IP = '127.0.0.1'
    TCP_PORT = 5563
    BUFFER_SIZE = 1024  # Normally 1024, but we want fast response
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((TCP_IP, TCP_PORT))
    array_string=pickle.dumps(array)
    sock.send(array_string)
    sock.close()

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind((TCP_IP, TCP_PORT))
    sock.listen(1)

    conn, info = sock.accept()
    while 1:
        data = serverSocket.recv(1024)
        if not data:break
    conn.send(data)  
    conn.close()

這里有一堆真正的新手錯誤。

  1. 您永遠無法將 TCP 套接字連接到自身。 必須有兩個不同的套接字。

  2. 如果你真的想得到你之前在監聽套接字上發送的數據,這個監聽套接字必須在客戶端連接之前創建、綁定和配置為監聽(或者,至少,與這個連接嘗試並行,在幾秒鍾內) ,所以連接嘗試會嘗試 - 但這很可能在本地主機上不起作用)。

  3. 如果兩者都阻塞,則不能在同一線程中等待連接和接受。 最簡單的方法是將客戶端和服務器端分離為 2 個不同的程序,並手動並行運行它們。 然后,調試成功后,您將能夠在同一進程的不同線程中執行此操作,或者使用事件驅動引擎。

雖然您可能無法將套接字連接到其自身以發送和接收數據,但您可以從以下示例中學習,這些示例受到您的代碼的啟發,該示例嘗試執行類似的操作。

import _thread
import pickle
import socket
import time


def main():
    """Run a server in a thread and start a client to talk to it."""
    _thread.start_new_thread(run_server, ('', 5563))
    run_client('localhost', 5563)


def run_server(host, port):
    """Handle all incoming connections by spawning worker threads."""
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind((host, port))
    server.listen(5)
    while True:
        _thread.start_new_thread(handle_connection, server.accept())


def handle_connection(client, address):
    """Answer an incoming question from the connected client."""
    print('Incoming connection from', address)
    client.settimeout(0.1)
    data = recvall(client)
    client.shutdown(socket.SHUT_RD)
    question = pickle.loads(data)
    answer = '''len(username) = {}
len(password) = {}
len(message) = {}'''.format(*map(len, question))
    client.sendall(answer.encode())
    client.shutdown(socket.SHUT_WR)
    client.close()
    print('Finished with', address)


def recvall(connection):
    """Receive all data from a socket and return as a bytes object."""
    buffer = bytearray()
    while True:
        try:
            data = connection.recv(1 << 12)
        except socket.timeout:
            pass
        else:
            if data:
                buffer.extend(data)
            else:
                return bytes(buffer)


def run_client(host, port):
    """Collect information from question and display returned answer."""
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    time.sleep(0.1) # wait for server to start listening for clients
    client.connect((host, port))
    time.sleep(0.1) # wait for handler thread to display connection
    username = input('Username: ')
    password = input('Password: ')
    message = input('Message: ')
    question = pickle.dumps((username, password, message))
    client.sendall(question)
    client.shutdown(socket.SHUT_WR)
    answer = recvall(client)
    client.shutdown(socket.SHUT_RD)
    client.close()
    print(answer.decode())
    time.sleep(0.1) # wait for handler to cleanly terminate execution

if __name__ == '__main__':
    main()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM