簡體   English   中英

如何在Python中使用套接字接受兩個連接

[英]How to accept two connections using sockets in Python

我正在做一個聊天程序。 但是目前只能有一個客戶。 我要如何使其能夠接受兩個客戶? 在套接字方面,我還是有點菜鳥的,所以您可以很詳盡地解釋一下嗎?

服務器代碼:

import socket

def mainFunc():
    host = ""
    port = 50000

    ipList = []
    nickNameList = []
    num = True

    s = socket.socket()
    s.bind((host, port))

    s.listen(1)
    c, addr = s.accept()

    print("Connection from: " + str(addr) + "\n")
    ipList.insert(0, str(addr))

    while True:
        data = c.recv(1024)
        if not data:
            break

        if num == True:
            nickNameList.insert(0, str(data))
            num = False
        else:
            print("From " + nickNameList[0] + ": " + str(data) + "\n")

            message = raw_input("Message you want to send: ")
            print("\n")

            c.send(message)

    c.close()

我嘗試將s.listen(1)更改為s.listen(2)。 但這似乎不允許第二個人進行聯系。 有人可以解釋為什么嗎?

一個accept呼叫將accept一個連接。 要接受兩種連接方式,呼叫accept兩次。

如果要順序連接兩個,但一次不超過一個, c, addr = s.accept()需要圍繞c, addr = s.accept()的循環c, addr = s.accept()及其c, addr = s.accept()所有內容。 然后它將接受一個連接,處理該連接,直到套接字關閉並執行break ,然后處理第二個連接,依此類推。

在這種情況下, listen積壓(即s.listen(2)在處理第一個連接時,它不會排隊等待2個以上的等待連接。 之后的任何人都會被拒絕。


如果要同時進行兩個連接,則必須執行以下兩項操作之一:

  • 多線程,每個連接都有一個線程。 (多處理和神奇的綠色線程gevent是相同的想法。)
  • 進行多路復用,反應器或proactor為所有連接處理非阻塞或異步I / O,而不是僅通過單個連接直接調用套接字。 (這個想法有很多變化,從協程調度程序(例如asyncio到圍繞select簡單循環)。)

在這種情況下,僅當您的程序太慢而無法跟上進入連接的速度時, listen積壓才真正重要。在這種情況下,拒絕新連接通常比接受新連接並進一步放慢速度要好,因此保持少量積壓是一個好主意。

但是由於您的連接處理程序會在每個套接字消息之后阻塞raw_input ,至少可以這樣說,這將是一個怪異的設計。 (不是阻塞部分,您可以通過為stdin分配線程, select條目,協程等來解決此問題。但是輸入實際上會發生什么。您只有8個連接,只有1個輸入。哪個連接可以得到結果用戶何時輸入內容?)


這是一個簡單的線程服務器:

def connection(c, addr):
    while True:
        # your existing while True loop

while True:
    c, addr = s.accept()
    t = threading.Thread(target=connection, args=(c, addr))
    t.start()

但是,對於您希望能夠以某種方式關閉的現實服務器,您將需要提供某種方式來關閉連接線程。 同樣,對於在客戶端之間進行交互的服務器(例如向一個用戶發送聊天消息給所有其他用戶),您需要某種方式在線程之間傳遞消息或在線程之間共享信息。 通常,每個連接最終需要兩個線程-一個線程在c.recvc.recv ,另一個線程在隊列上c.recv ,並與其他用戶的消息一起調用c.send


對於多路復用服務器,不同的方法看起來非常不同,但是所有方法都有很好的示例。 asyncioselectors了他們的榜樣, Socket編程HOWTOselect的例子,而谷歌對於像扭曲,GEVENT等第三方庫的例子


附帶說明一下,您似乎希望send肯定能一次發送完整的消息,而另一端的recv將接收到整個消息,而不會收到其他任何消息。 TCP不能保證沒有這種事情。 有關更多詳細信息請參見套接字是字節流,而不是消息流

另外,在nickNameList.insert(0, str(data))str是什么? 在Python 2.x中, data已經是一個str ,因此這沒有充分的理由浪費了額外的副本。 在Python 3.x中, data是一個bytes ,因此這會將其轉換為字符串表示形式,例如"b'0Cool'"而不是"0Cool" ,這幾乎肯定不是您想要的。

暫無
暫無

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

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