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

나는 당신의 힌트를 시험해 본다. 그러나 이것 또한 내가 예외 (이 경우 메시지 박스) 인 – Francesco

+0

을 쳐다 보았다. socket.Close를 호출하는 예제를 보자. foreach 루프에 넣고 socket.Close()를 제거해야한다. ; foreach 루프 외부에서 호출 – MethodMan

답변

1

당신은 socketincoming에 대한 참조를 덮어 쓰는 것 같다. 나는 이것들이 그 반의 들판이라고 생각한다. 나는 당신이이 객체들을 모아 놓고 종료 할 때 그것들을 모두 닫을 필요가 있다고 생각합니다.

또한 스레드 중단은 스레드가 중단 될 때 수행중인 작업을 알지 못하기 때문에 바람직하지 않습니다. 플래그를 설정하고 루프에서 확인하여 정상적인 종료를 만드는 것이 더 나은 방법입니다. 이것은 귀하의 예외의 원인 일 수 있습니다. 스레드를 중단하지 말고 모든 것을 종료 할 적절한 방법을 찾으십시오. 이런 식으로 버그가없는 경로를 찾을 가능성이 더 큽니다.

while (true) 루프를 모두 while (_isRunning)으로 바꿉니다. 그것을 공개 값을 가진 클래스의 필드로 설정하십시오. 닫을 때 false로 설정하면 스레드가 정상적으로 종료됩니다.

+0

내가 진짜 예를 들어 줄 수있어. 나는 C#에 능숙하지 않아 숙제를 위해이 소프트웨어를해야 해. 어쨌든 당신의 대답을 주셔서 감사합니다 :) – Francesco

+1

이것을 고려하십시오. 두 개의 클라이언트가 받아 들여지면, 두 번째 클라이언트의 경우'incoming = socket.Accept();'는 첫 번째 클라이언트의'incoming '을 덮어 씁니다. 비슷하게,'thrReceive'는 덮어 씌여 질 것입니다. 그런 다음 나중에 close/abort를 호출하면 마지막 클라이언트에서만 작동하게되고 첫 번째 클라이언트의 소켓/스레드는 계속 활성화됩니다. –

+0

ok 두 클라이언트가 서버에 연결하는 경우에 해당됩니다. 그러나 클라이언트없이이 서버를 시작하면 – Francesco

관련 문제