2010-03-16 37 views
2

有沒有辦法處理與C#中的套接字會話?我的問題與會話的.NET TCP套接字

例子:
我有一個socket監聽端口5672。

TcpListener socket = new TcpListener(localAddr, 5672); 
socket.Start(); 
Console.Write("Waiting for a connection... "); 

// Perform a blocking call to accept requests. 
TcpClient client = socket.AcceptTcpClient(); 
Console.WriteLine("Connected to client!"); 

,我有兩個客戶端將發送一個字節的服務器。客戶端A發送0x1,客戶端B發送0x2。 從服務器端,我讀這個數據是這樣的:

Byte[] bytes = new Byte[256]; 
String data = null; 

NetworkStream stream = client.GetStream(); 
while ((stream.Read(bytes, 0, bytes.Length)) != 0) 
{ 
    byte[] answer = new ... 
    stream.Write(answer , 0, answer.Length); 
} 

然後客戶端A發送爲0x11。 我需要一種方法來知道這個客戶端是以前發送「0x1」的相同。

回答

4

每個TcpClient實例用於不同的連接。 TCP中的連接由四部分組成:源IP,源端口,目標IP,目標端口。因此,即使您擁有相同的目標IP和端口,以及相同的源端口,您也有兩個不同的連接。

一個客戶端發送的數據不會與其他客戶端發送的數據混合在一起。客戶端在連接上發送的數據將按照該連接順序接收。

Sessions成爲問題的唯一時間是在連接關閉後記住客戶端。

+0

我不明白數據如何混合。在我讀取第一個客戶端發送的數據後,TcpClient對象被銷燬。並讀取以下數據我必須做socket.AcceptTcpClient();再次。你能發佈一個演示代碼來檢測客戶端A在sendig 0x1後發送0x11的時間嗎?謝謝 – 2010-03-16 19:39:10

+0

@ZeCarlos:你真的需要關閉'TcpClient'實例嗎?爲什麼不重用它們?每個人都可以從一個客戶端獲得一個完整的數據流。 – 2010-03-16 19:43:29

+0

你說得對。我可以重用TcpClient及其關聯的流。對不起,我的無知。謝謝 – 2010-03-16 20:09:30

0

您可能需要實施自己的協議以識別客戶端。也許定義一個字節塊,除了數據外,還包含一個客戶端標識符。

+0

感謝您的回答,但我不能那樣做。我正在實現一個通過TCP進行通信的協議。我無法修改客戶發送的信息。 – 2010-03-16 19:12:29

+0

@ZeCarlos:誰定義客戶端發送的數據格式? – 2010-03-16 19:16:00

+0

其協議。 AMQP就是這種情況。 http://www.amqp.org/confluence/download/attachments/720900/amqp0-9.pdf?version = 1&modificationDate = 1183135701000 但是,幀中的數據沒有任何字段標識客戶端。我通過了解客戶端使用的IP和端口來識別。我正在尋找一些自動完成的方法 – 2010-03-16 19:25:31

0

您需要某種認證或預先協商的令牌,並且所有這些都用某種鹽加密。

+1

你當然不需要任何鹽漬哈希或加密的身份識別手段,但取決於特定的需求,它可能會被推薦。 – 2010-03-16 19:12:15

1

關於如何在Web世界(HTTP)中實現會話的現有文獻很多。

一個關鍵是你是關閉客戶端連接還是持久性?如果它們是持久的,那麼只需通過它們的對象引用來標識它們。如果不是,則...

1)您可以根據源IP地址進行簡單會話。但是,如果多個客戶端位於NAT防火牆之後,共享IP,那麼這不起作用,請參閱下一個選項。

2)使用一個「cookie」

3)使用身份驗證,以確定每個客戶

每個選項除了基於IP的會話需要添加一些東西到協議本身。

有些事情要記住套接字。遠程IP +遠程端口唯一標識客戶端TCP套接字。來自同一個遠程客戶端的多個連接將具有不同的遠程端口。但是,如果套接字關閉,則不能依賴該套接字,因爲遠程操作系統可能會在新舊連接超時後重新啓動遠程端口以建立新連接。