Как заставить TCP-сервер обрабатывать несколько клиентов? - PullRequest
0 голосов
/ 03 марта 2019

Я пытаюсь создать сервер Python, к которому могут подключиться несколько клиентов, но я столкнулся с проблемой, я перепробовал все, что нашел в интернете.Я использую ноутбук с Windows 7 и процессор I3.

Этот файл называется tcp :

import socket

def make_server (ip,port):
    try:
        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server.bind((ip, port))
        server.listen(1)
        return server
    except Exception as ex:
        print(ex)
        return None


def accept(server):
    conn, addr = server.accept()
    return conn

def make_client():
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    return client

def client_connect(client,ip,port):
    client.connect((ip,port))

def sendall(conn,mess):
    conn.send(str(mess).encode("utf-8"))

def rec(conn,rate):
    mess = conn.recv(rate).decode("utf-8")
    return mess

def close(client):
    client.close()

Это сервер :

from multiprocessing import Process
from random import randint
import tcp
import sys


def start(sip, sport):
    print("Making sob server...")
    print("id= {}".format(sport))
    sserver = tcp.make_server(sip, sport)
    print("Sub Server Started!")
    sconn = tcp.accept(sserver)
    tcp.sendall(sconn, "connected!!")
    while True:
        try:
            tcp.sendall(sconn, randint(0, 100))
        except Exception as ex:
            print("")
            print("From server {} error:".format(port))
            print(ex)
            print("")
            break


ip = "192.168.0.102"
port = 8000
subport = 9000
server = tcp.make_server(ip, port)
if server is None:
    sys.exit(0)
print("Started!")
while True:
    print("Wating for new connection!")
    con = tcp.accept(server)
    print("Connected!")
    subport = subport + 1
    tcp.sendall(con, subport)
    print("New Port Sent!")
    print("New Port = {}".format(subport))
    subs = Process(target=start, args=(ip, subport))
    subs.start()
    subs.join()

Это клиент :

import tcp
import time

nport = 0
ip = "192.168.0.102"
port = 8000
client = tcp.make_client()
tcp.client_connect(client,ip,port)
nport = tcp.rec(client,1024)
print(nport)
tcp.close(client)
nport = int(nport)
time.sleep(1)
print(nport)
client = tcp.make_client()
tcp.client_connect(client,ip,nport)
while True:
    mess = tcp.rec(client, 1024)
    if(mess):
        print(mess)

Ошибка:

[WinError 10048]Only one usage of each socket address (protocol/network address/port) is normally permitted Python

Не стесняйтесь изменять что-либоты хочешь.Если вам нужна информация в плюсе, просто спросите.

1 Ответ

0 голосов
/ 03 марта 2019

Вы создаете сокет в клиенте с tcp.make_client.Затем вы используете этот сокет для подключения к серверу через tcp.client_connect.Предположительно, вы успешно получили новый номер порта обратно с сервера.Но затем вы пытаетесь повторно использовать тот же сокет для подключения к этим портам.

Это примерная причина вашей ошибки: сокет может использоваться только для одного соединения TCP,Если вы хотите создать новое соединение, вы должны сначала создать новый сокет.

При этом, если вы просто пытаетесь создать сервер, который будет принимать несколько соединений, вы делаете это слишком сложным.Сервер может получать любое количество подключений через свой единственный порт прослушивания, если каждый клиент использует различную комбинацию адреса / порта.

Один из способов структурировать это на сервере - это что-то вроде этого:

# Create and bind listening socket
lsock = socket.socket()
lsock.bind(('', port))
lsock.listen(1)
while True:    
    csock, addr = lsock.accept()
    print("Got connection from {}".format(addr))

    # Start sub-process passing it the newly accepted socket as argument
    subs = Process(target=start, args=(csock, ))
    subs.start()

    # Close our handle to the new socket (it will remain open in the 
    # sub-process which will use it to talk to the client)
    csock.close()

    # NOTE: do not call subs.join here unless you want the parent to *block* 
    # waiting for the sub-process to finish (and if so, what is the point in 
    # creating a sub-process?)

Есть также несколько других способов сделать это: вы можете создать несколько потоков для обработки нескольких соединений, или вы можете обрабатывать все соединения в одном потоке, используя select или с помощью асинхронного ввода-вывода.

Клиент, как правило, намного проще - так как он обычно заботится только о своем собственном соединении - и не заботится о том, каким образом реализован сервер:

sock = socket.socket()
sock.connect((ip, port))
while True:
    sock.send(...)
    sock.recv(...)

Если клиент не хочет снова подключиться к тому же серверу, он просто создает второй сокет и вызывает метод connect с тем же IP-адресом и портом сервера.

Обычно клиенту никогда не требуетсяуказать свой собственный порт, только порт сервера.Он просто вызывает connect, и клиентская операционная система выбирает для него неиспользуемый порт.Поэтому в первый раз, когда клиент создает сокет и подключает его ( к порту прослушивания сервера ), клиентская ОС может выбрать порт 50001. В следующий раз, когда он создает и подключает сокет, он может получить50002 и тд.(Точные номера портов зависят от реализации операционной системы и других факторов, например, от того, какие другие программы работают и создают соединения.)

Итак, с учетом IP-адреса клиента 192.168.0.101 и IP-адреса сервера 192.168.0.102, ипри условии, что сервер прослушивает порт 8000, это приведет к следующим двум соединениям:

  • (192.168.0.101/50001) ====> (192.168.0.102/8000)
  • (192.168.0.101/50002) ====> (192.168.0.102/8000)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...