简体   繁体   中英

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM