2012-12-30 217 views
1

我正在創建一個由套接字和線程管理的客戶端/服務器應用程序。 我想知道如何正確關閉套接字和相關的線程。 這是我的代碼:關閉線程套接字

protected override void OnFormClosing(FormClosingEventArgs e) 
{ 
    base.OnFormClosing(e); 

    try 
    { 
     if (UserList.Count > 0) 
     { 
      foreach (User user in UserList) 
      { 
       Socket socketUser = user.getSocket(); 
       socketUser.Send(Encoding.ASCII.GetBytes("!close")); 
       socketUser.Close(); 
      } 
     } 
     thrAccept.Abort(); 
     thrReceive.Abort(); 
     socket.Close(); 
     incoming.Close(); 

     Application.Exit(); 
    } 
    catch 
    { 
     MessageBox.Show("aasa"); 
    } 
} 

private void connectBtn_Click(object sender, EventArgs e) 
{ 
    string port=portNum.Text; 
    string welcome = "Server up and running - " + System.DateTime.Now.GetDateTimeFormats()[0] + " " + DateTime.Now.ToString("HH:mm") + "\n" + "Listening Port: " + port + "\n"; 
    socket.Bind(new IPEndPoint(IPAddress.Any, Convert.ToInt32(portNum.Text))); 
    socket.Listen(3); 

    thrAccept = new Thread(new ThreadStart(Accept)); 
    serverLog.AppendText(welcome + "\n"); 
    thrAccept.Start(); 
    connectBtn.Enabled = false; 
} 

private void Accept() 
{ 
    while (true) 
    { 
     incoming = socket.Accept(); 
     thrReceive = new Thread(new ThreadStart(Receive)); 
     thrReceive.Start(); 
    } 
} 

private void Receive() 
{ 
    User user = new User();//create an istance for the class User 

    while (true) 
    { 
     byte[] buffer = new byte[64]; 
     incoming.Receive(buffer); 
     // the program continue.... 

如何正確關閉插座?

類用戶

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Net.Sockets; 
using System.Threading; 

namespace HW2_SERVER 
{ 
    class User 
    { 
     public string username; 
     public Socket S; 
     public string role; 
     public bool managed; 
     public User() 
     { 
      username = ""; 
      S = null; 
      role = ""; 
      managed = false; 

     } 

     public void setManage(bool i) 
     { 
      managed = i; 
     } 
     public void setUsername(string u) 
     { 
      username = u; 
     } 
     public void setSocket(Socket sock) 
     { 
      S = sock; 
     } 
     public void setRole(string r) 
     { 
      role = r; 
     } 
     public bool getManaged() 
     { 
      return managed; 
     } 
     public string getUsername() 
     { 
      return username; 

     } 
     public Socket getSocket() 
     { 
      return S; 
     } 
     public string getRole() 
     { 
      return role; 
     } 
    } 
} 
+0

你有沒有想過調用socket.Shutdown(SocketShutdown.Both);在調用socket.Close之前? – MethodMan

+0

我嘗試一下你的提示,但也是這樣的我發現異常(在這種情況下是messagebox) – Francesco

+0

看看你調用socket.Close的例子,你也應該把它放在foreach循環中,並移除socket.Close() ;在foreach循環之外調用 – MethodMan

回答

1

你似乎覆蓋你參考socketincoming。我認爲這些是課堂上的領域。我認爲您需要保留這些對象的集合,並在關閉時關閉所有這些對象。

另外,中止線程是一個壞主意,因爲您不知道線程在被中止時正在執行什麼操作。通過設置一個標誌並在循環中檢查標誌,進行正常關閉被認爲是更好的做法。這可能是你例外的原因。我建議你不要中止這些線程,而是找到一種合適的方法來關閉所有的東西。你更可能以這種方式找到無缺陷的路徑。

我會用while (_isRunning)替換您的while (true)循環。將其設置爲具有公共價值的課程。當您關閉時,將其設置爲false,線程將優雅地退出。

+0

你能給我一個真實的例子,我對C#不熟練,而且我必須做這個軟件做家庭作業。不管怎樣,謝謝你的回答:) – Francesco

+1

考慮一下。如果接受兩個客戶端,那麼對於第二個客戶端,incoming = socket.Accept();'將覆蓋來自第一個客戶端的'incoming'。同樣,'thrReceive'將被覆蓋。然後,當你調用close/abort時,你只會在最後一個客戶端上運行,並且第一個客戶端的套接字/線程仍然活着。 –

+0

好的這是真的,我有兩個客戶端將連接到服務器,但如果我啓動服務器沒有客戶端這種方式應該工作 – Francesco