2012-12-30 218 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