简体   繁体   English

如何在 Python 中从同一个套接字发送和接收?

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

I'm am trying to write a client program in Python that can send and receive from the same socket, but it is always giving me the same error which address is already in use.我正在尝试用 Python 编写一个可以从同一个套接字发送和接收的客户端程序,但它总是给我同样的错误,哪个地址已经在使用中。 Here is the function I'm trying to write.这是我正在尝试编写的函数。

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()

There is a bunch of truly newbie errors here.这里有一堆真正的新手错误。

  1. You can't ever connect a TCP socket to itself.您永远无法将 TCP 套接字连接到自身。 There must be two different sockets.必须有两个不同的套接字。

  2. If you really want to get the data you sent earlier at a listening socket, this listening socket must be created, bound and configured to listen before the client side connects (or, at least, in parallel to this connect attempt, in a few seconds, so the connect attempt will try - but this very likely won't work on localhost).如果你真的想得到你之前在监听套接字上发送的数据,这个监听套接字必须在客户端连接之前创建、绑定和配置为监听(或者,至少,与这个连接尝试并行,在几秒钟内) ,所以连接尝试会尝试 - 但这很可能在本地主机上不起作用)。

  3. You can't wait on connect and on accept in the same thread if both are blocking.如果两者都阻塞,则不能在同一线程中等待连接和接受。 The simplest approach is to separate the client side and the server side to 2 different programs and run them manually in parallel.最简单的方法是将客户端和服务器端分离为 2 个不同的程序,并手动并行运行它们。 Then, after successful debugging, you will be able to do this in different threads of the same process, or using an event-driven engine.然后,调试成功后,您将能够在同一进程的不同线程中执行此操作,或者使用事件驱动引擎。

While you may not be able to connect a socket to itself to send and receive data, you might be able to learn from the following example inspired by your code that attempts to do something similar.虽然您可能无法将套接字连接到其自身以发送和接收数据,但您可以从以下示例中学习,这些示例受到您的代码的启发,该示例尝试执行类似的操作。

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