2013-09-25 51 views
1

我是新來的套接字,所以我嘗試創建一個服務器和交換消息的客戶端。我在C#中創建了一個,但它給了我奇怪的錯誤,它一旦我啓動服務器就會凍結並顯示「無響應」消息...當我連接服務器時,客戶端也會發生同樣的情況,但問題在於關閉其中的任何一個時。 。其他應用程序顯示了更新,以便IDK的是什麼問題,反正這裏是U使用的代碼服務器和客戶端始終沒有響應

服務器類

Socket Soc; 
static ushort MaxClients = 1000; 
static List<Socket> ClientList = new List<Socket>(MaxClients); 
static bool ServerStarted; 
public Server() 
{ 
    InitializeComponent(); 
    button1.Enabled = false; 
    button2.Enabled = false; 
} 

private void button1_Click(object sender, EventArgs e) // Send 
{ 
    string MessageToSend = textBox1.Text; 
    byte[] Buffer = Encoding.Default.GetBytes(MessageToSend); 
    foreach (var client in ClientList) 
    { 
     Soc.Send(Buffer, 0, Buffer.Length, SocketFlags.None); 
    } 
    textBox2.Text += " Message Sent To Clients : " + MessageToSend + Environment.NewLine; 
} 

private void button3_Click(object sender, EventArgs e) // Start 
{ 
    StartServer("25.21.113.163", 5000); 
} 

private void button2_Click(object sender, EventArgs e) // Stop 
{ 
    CloseServer(); 
} 

private void button4_Click(object sender, EventArgs e) // Exit 
{ 
    CloseServer(); 
    Application.Exit(); 
} 

public void StartServer(string Ip, ushort Port) 
{ 
    Soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
    Soc.Bind(new IPEndPoint(IPAddress.Parse(Ip), Port)); 
    textBox2.Text += " Server Is Created On Ip : " + Ip + ", Port : " + Port + Environment.NewLine; 
    Soc.Listen(MaxClients); 
    textBox2.Text += " Server Is Listening to Clients Now... " + Environment.NewLine; 
    ServerStarted = true; 
    button1.Enabled = true; 
    button2.Enabled = true; 
    button3.Enabled = false; 
    label3.Text = ClientList.Count.ToString() + "/" + MaxClients; 
    ReceiveData(); 
} 

public void ReceiveData() 
{ 
    while (true) 
    { 
     var Client = Soc.Accept(); 
     ClientList.Add(Client); 
     label3.Text = ClientList.Count.ToString() + "/" + MaxClients; 
     textBox2.Text += " Client Located At Ip : " + Client.RemoteEndPoint.ToString().Split(':')[0].ToString() + " Is Now Connected To Server " + Environment.NewLine; 
     while (true) 
     { 
      byte[] ReceivedBytes = new byte[1024]; 
      int ReceivedDataLength = Client.Receive(ReceivedBytes, 0, ReceivedBytes.Length, SocketFlags.None); 
      string MessageFromClient = Encoding.Default.GetString(ReceivedBytes, 0, ReceivedDataLength); 
      textBox2.Text += " Message Sent to Server : " + MessageFromClient + Environment.NewLine; 
     } 
    } 
} 

public void CloseServer() 
{ 
    Soc.Close(); 
    ServerStarted = false; 
    textBox2.Text += " Server Is Closed Now... " + Environment.NewLine; 
    button3.Enabled = true; 
    button2.Enabled = false; 
    button1.Enabled = false; 
} 

Client類

Socket Client; 
public Form1() 
{ 
    InitializeComponent(); 
    button1.Enabled = false; 
    button2.Enabled = false; 
} 

private void button1_Click(object sender, EventArgs e) // Send 
{ 
    string MessageToSend = textBox2.Text; 
    byte[] Buffer = Encoding.Default.GetBytes(MessageToSend); 
    Client.Send(Buffer, 0, Buffer.Length, SocketFlags.None); 
    textBox1.Text += " Sent Message To Server Is : " + MessageToSend + Environment.NewLine; 
} 

private void button2_Click(object sender, EventArgs e) // LogOut 
{ 
    ClientClose(); 
} 

private void button3_Click(object sender, EventArgs e) // Connect 
{ 
    ConnectToServer("25.21.113.163", 5000); 
} 

private void button4_Click(object sender, EventArgs e) // Exit 
{ 
    ClientClose(); 
    Application.Exit(); 
} 

public void ConnectToServer(string Ip, ushort Port) 
{ 
    try 
    { 
     Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
     Client.Connect(Ip, Port); 
     textBox1.Text += " You Are Now Connected To Server Hosted On Ip : " + Client.RemoteEndPoint + Environment.NewLine; 
     button1.Enabled = true; 
     button2.Enabled = true; 
     button3.Enabled = false; 
     ReceiveData(); 
    } 
    catch 
    { 
     textBox1.Text += " Server In Offline Now " + Environment.NewLine; 
    } 
} 

public void ReceiveData() 
{ 
    while (true) 
    { 
     byte[] ReceivedBytes = new byte[1024]; 
     int ReceivedBytesLength = Client.Receive(ReceivedBytes, 0, ReceivedBytes.Length, SocketFlags.None); 
     string ReceivedMessage = Encoding.Default.GetString(ReceivedBytes, 0, ReceivedBytesLength); 
     textBox1.Text += " Received Message From Server Is : " + ReceivedMessage + Environment.NewLine; 
    } 
} 

public void ClientClose() 
{ 
    button1.Enabled = false; 
    button2.Enabled = false; 
    button3.Enabled = true; 
    Client.Dispose(); 
    Client.Close(); 
    textBox1.Text += " You Are Disconnected From Server" + Environment.NewLine; 
} 

我想知道我做錯了什麼?我該如何擺脫這兩個應用程序的愚蠢的「無響應」狀態?

回答

0

首先,讓我們對您的代碼進行更正,以便它能夠正常工作,非常感謝我給出了一些Asynchronous Socket教程,這些教程比Synchronous更容易。

您的問題是在這條線:

public void ReceiveData() 
{ 
    while (true) 
    { 
     var Client = Soc.Accept(); 
     ClientList.Add(Client); 
     label3.Text = ClientList.Count.ToString() + "/" + MaxClients; 
     textBox2.Text += " Client Located At Ip : " + Client.RemoteEndPoint.ToString().Split(':')[0].ToString() + " Is Now Connected To Server " + Environment.NewLine; 
     while (true) 
     { 
      byte[] ReceivedBytes = new byte[1024]; 
      int ReceivedDataLength = Client.Receive(ReceivedBytes, 0, ReceivedBytes.Length, SocketFlags.None); 
      string MessageFromClient = Encoding.Default.GetString(ReceivedBytes, 0, ReceivedDataLength); 
      textBox2.Text += " Message Sent to Server : " + MessageFromClient + Environment.NewLine; 
     } 
    } 
} 

這是由於兩個原因: 1)你必須聽傳入連接到一個單獨的線程。 2)你必須在一個單獨的線程中監聽每個客戶端,所以它們不會彼此阻塞。在您的示例中,第二個while(true)正在偵聽客戶端阻止服務器套接字接受其他客戶端。將其重構爲:

public void ReceiveData() 
    { 
     new Thread(() => 
     { 
      while (true) 
      { 
       var Client = Soc.Accept(); 
       ClientList.Add(Client); 
       label3.Text = ClientList.Count.ToString() + "/" + MaxClients; 
       textBox2.Text += " Client Located At Ip : " + Client.RemoteEndPoint.ToString().Split(':')[0].ToString() + " Is Now Connected To Server " + Environment.NewLine; 

       new Thread(() => 
       { 
        while (true) 
        { 
         byte[] ReceivedBytes = new byte[1024]; 
         int ReceivedDataLength = Client.Receive(ReceivedBytes, 0, ReceivedBytes.Length, SocketFlags.None); 
         string MessageFromClient = Encoding.Default.GetString(ReceivedBytes, 0, ReceivedDataLength); 
         textBox2.Text += " Message Sent to Server : " + MessageFromClient + Environment.NewLine; 
        } 
       }).Start(); 
      } 
     }).Start(); 
    } 

此方法爲每個客戶端使用單獨的線程處理來自客戶端的接收數據。

我還增加了對客戶端應用程序代碼:

public void ReceiveData() 
    { 
     new Thread(() => 
     { 
      while (true) 
      { 
       byte[] ReceivedBytes = new byte[1024]; 
       int ReceivedBytesLength = Client.Receive(ReceivedBytes, 0, ReceivedBytes.Length, SocketFlags.None); 
       string ReceivedMessage = Encoding.Default.GetString(ReceivedBytes, 0, ReceivedBytesLength); 
       textBox1.Text += " Received Message From Server Is : " + ReceivedMessage + Environment.NewLine; 
      } 
     }).Start(); 
    } 

在將來看看Asynchronous Sockets,你將不再需要處理多線程問題。 http://msdn.microsoft.com/en-us/library/fx6588te.aspx http://msdn.microsoft.com/en-us/library/bbx2eya8.aspx

編輯更新的客戶端/ SER

+0

以及服務器應用程序掛起併成爲啓動它..甚至沒有得到一個客戶端連接後沒有響應..這同樣適用於客戶當我按下它連接也變得凍結了,所有的發送/接收消息都在工作,但是除非關閉其中任何一個,否則你不會看到。你看到另一個應用程序更新了..我不知道同步套接字是否被設計爲那個笨蛋但我不在意很多關於Syncs的信息,絕不會使用em,但我需要知道的是y應用程序掛起 –

+0

複製更新後的代碼。注意:從UI線程以外更新TextBox值時會出現錯誤,但簡單的Google搜索將有所幫助;) – Lev

+0

它做得很好,但是當我發送客戶端文本時,它給了我一個錯誤,表明沒有給出地址idk那是什麼意味着似乎一切正常 另一個問題,如果我使用異步套接字將不得不調用while(true)或它處理與線程有關的所有東西? –