2011-05-21 116 views
0

我試圖建立與以下代碼簡單的客戶端 - 服務器應用程序:能夠處理併發請求的TcpConnection。客戶端 - 服務器

//SERVER 
IPAddress ipAd = IPAddress.Parse("192.163.10.101"); 
TcpListener myList = new TcpListener(ipAd, 8001); 
myList.Start(); 

Console.WriteLine("The server is running at port 8001..."); 
Console.WriteLine("The local End point is :" + myList.LocalEndpoint); 
Console.WriteLine("Waiting for a connection....."); 

Socket s = myList.AcceptSocket(); 
Console.WriteLine("Connection accepted from " + s.RemoteEndPoint); 

//CLIENT 
TcpClient tcpclnt = new TcpClient(); 
Console.WriteLine("Connecting....."); 
tcpclnt.Connect("192.163.10.101",8001); 
Console.WriteLine("Connected"); 

這實際上做什麼,我需要的,其中客戶端可以連接到服務器。但是,當我嘗試運行客戶端的多個實例以連接服務器時,服務器僅接受第一個要連接的客戶端。這意味着像一個一對一的連接,其中只有一個客戶端可以連接到客戶端。但是,我需要的是讓服務器能夠接受來自多個客戶端的連接。

如果有人能指出我可能的解決方案,我真的很感激!謝謝!

+0

如果第一個客戶端斷開連接,您可以連接第二個客戶端嗎? – Oded 2011-05-21 05:54:29

+0

是的,我可以。我想實現的是讓服務器接受多個連接的客戶端。 :)感謝您的迴應! – Smiley 2011-05-21 05:56:05

回答

1

您需要再次調用AcceptSocket接受另一個套接字。
一個典型的設計是必須調用BeginAcceptSocket並在回調函數EndAcceptSocket中調用客戶端處理到它自己的線程(或使用異步方法的工作線程),然後再次調用BeginAcceptSocket。

這個片段沒有經過測試,但應該是或多或少的正確/讓你朝着正確的方向思考。

class Server 
{ 
    public Server() 
    { 
     TcpListener listener = null; 

     // init the listener 

     listener.BeginAcceptSocket((ar) => AcceptLoop(ar, listener),null); 
    } 

    public void HandleClientSocketRead(IAsyncResult ar, byte[] recvBuffer, Socket clientSocket) 
    { 
     int recvd = clientSocket.EndReceive(ar); 
     //do something with the data 
     clientSocket.BeginReceive(recvBuffer, 0, 1024, SocketFlags.None, (ar2) => HandleClientSocketRead(ar2, recvBuffer, clientSocket), null); 
    } 

    public void AcceptLoop(IAsyncResult ar, TcpListener listener) 
    { 
     Socket clientSocket = listener.EndAcceptSocket(ar); // note that this can throw 
     byte[] recvBuffer = new byte[1024]; 

     clientSocket.BeginReceive(recvBuffer, 0, 1024, SocketFlags.None, (ar2) => HandleClientSocketRead(ar2, recvBuffer, clientSocket), null); 

     listener.BeginAcceptSocket((ar) => AcceptLoop(ar, listener), null); 
    } 
} 
+0

如果我使用此代碼作爲我的服務器,是否必須更改我的客戶端的某些部分?我很抱歉,但我想我很困惑。謝謝您的幫助! :) – Smiley 2011-05-21 06:31:49

+0

沒有。在服務器上執行異步操作和在客戶端上執行同步操作是完全可以接受的。 – Yaur 2011-05-21 06:35:23

0

如果您正在尋找寫一個服務器,一個好的設計是有一個[服務器] .exe和一個[客戶] .exe文件。 [server] .exe當然會接受和處理所有傳入連接,維護客戶端套接字並執行您需要的任何操作。下面是一個非常編寫服務器接受多個客戶套接字的基本示例,並將它們存儲在List對象中。但是,這不是多線程的,所以代碼不會阻塞。

[服務器] .EXE

//----------------------------------------------------------------------------- 
// <copyright file="Program.cs" company="DCOM Productions"> 
//  Copyright (c) DCOM Productions. All rights reserved. 
// </copyright> 
//----------------------------------------------------------------------------- 

namespace MultiSocketServerExample { 
    using System; 
    using System.Net.Sockets; 
    using System.Net; 
    using System.Collections.Generic; 

    class Program { 

     static List<Socket> m_ConnectedClients = new List<Socket>(); 

     static void Main(string[] args) { 
      Socket host = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      host.Bind(new IPEndPoint(IPAddress.Any, 9999)); 
      host.Listen(1); 

      while (true) { 
       m_ConnectedClients.Add(host.Accept()); 
       Console.WriteLine("A client connected."); 
      } 
     } 
    } 
} 

然後與客戶合作:(同樣,非常基本的例子)

m_ConnectedClients[0].Send(Encoding.ASCII.GetBytes("hello!"); 

網絡編程與Socket類是很多在我看來更容易,然後使用TcpListener和TcpClient。我這樣說的原因是它已經是一個非常好用的實現,並且通過使用TcpListener和TcpClient創建更多抽象,減少了理解正在發生的事情的能力(在我看來)。

+0

如果我打算爲我的服務器使用這種類型的代碼,那麼我可能應該把我的代碼放在while循環裏吧?我的意思是因爲我必須接受來自用戶的一些輸入並用服務器處理它。 – Smiley 2011-05-21 11:02:01

+0

想想你的應用程序需要做什麼。您需要一個連接到服務器的客戶端,可以接受多個命令(正在進行),併發送給服務器並由其處理。以該順序。 1)寫代碼連接2)接受輸入3)發送到服務器4)等待響應(這是客戶端的命令),所以正確,你需要一個循環來接受輸入。在輸入準備好之後立即發送並等待響應,然後循環並重新開始 – 2011-05-21 20:41:24

相關問題