2014-01-18 4 views
0

У меня есть этот сокет TCP приложение чат с YouTubeкак закрыть TCP сокет-соединение в C#

стороне сервера

int i; 
TcpListener server = new TcpListener(IPAddress.Any, 1980); 
NetworkStream stream; 
TcpClient client; 
byte[] datalength = new byte[4]; 

public Form1() 
{ 
    InitializeComponent(); 
} 

public void ServerReceive() 
{ 
    stream = client.GetStream(); 
    new Thread(() => 
    { 
     while ((i = stream.Read(datalength, 0, 4)) != 0) 
     { 

      byte[] data = new byte[BitConverter.ToInt32(datalength, 0)]; 
      stream.Read(data, 0, data.Length); 
      this.Invoke((MethodInvoker)delegate 
      { 
       txtLog.Text += System.Environment.NewLine + "Client : " + Encoding.Default.GetString(data); 
      }); 
     } 
    }).Start(); 

} 

public void ServerSend(string msg) 
{ 
    stream = client.GetStream(); 
    byte[] data; 
    data = Encoding.Default.GetBytes(msg); 
    int length = data.Length; 
    byte[] datalength = new byte[4]; 
    datalength = BitConverter.GetBytes(length); 
    stream.Write(datalength, 0, 4); 
    stream.Write(data, 0, data.Length); 
} 

private void btnSend_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     if (client.Connected) 
     { 
      ServerSend(txtSend.Text); 
     } 
    }catch 
    { 
     txtLog.Text += "connection close"; 
    } 
} 

private void btnListen_Click(object sender, EventArgs e) 
{ 
    server.Start(); 

    new Thread(() => 
    { 
     client = server.AcceptTcpClient(); 

     if (client.Connected) 
     { 
      ServerReceive();      
     } 
    }).Start(); 

} 

стороне клиента

int i; 
TcpClient client; 
NetworkStream stream; 
byte[] datalength = new byte[4]; 

public Form1() 
{ 
    InitializeComponent(); 
} 

public void ClientReceive() 
{ 

    stream = client.GetStream(); 
    new Thread(() => 
     { 
      while ((i = stream.Read(datalength, 0, 4)) != 0) 
      { 

       byte[] data = new byte[BitConverter.ToInt32(datalength, 0)]; 
       stream.Read(data, 0, data.Length); 
       this.Invoke((MethodInvoker)delegate 
       { 
        txtLog.Text += System.Environment.NewLine + "Server : " + Encoding.Default.GetString(data); 
       }); 
      } 
     }).Start(); 

} 

public void ClientSend(string msg) 
{ 
    stream = client.GetStream(); 
    byte[] data; 
    data = Encoding.Default.GetBytes(msg); 
    int length = data.Length; 
    byte[] datalength = new byte[4]; 
    datalength = BitConverter.GetBytes(length); 
    stream.Write(datalength, 0, 4); 
    try 
    { 
     stream.Write(data, 0, data.Length); 
    } 
    catch 
    { 
     stream.Dispose(); 
     client.Close(); 
    } 
} 

private void btnConnect_Click(object sender, EventArgs e) 
{ 

    try 
    { 
     client = new TcpClient("127.0.0.1", 1980); 
     ClientReceive(); 
     txtLog.Text += Environment.NewLine+ "Connected"; 

    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
} 

private void btnSend_Click(object sender, EventArgs e) 
{ 

    if (client.Connected) 
    { 
     ClientSend(txtSend.Text); 
    } 
} 

сейчас, все эти работы отлично подходит для я, однако каждый раз, когда я закрываю одну из них, я получаю эту ошибку. «Невозможно прочитать данные из транспортного соединения: существующее соединение было принудительно закрыто удаленным хостом». на ClientReceive() или ServerReceive()

Как я могу поймать эту ошибку, если один из них внезапно закрыт или сетевой кабель внезапно отключился? заранее заранее

+0

С блоком 'try..catch'. – CodeCaster

ответ

0

В этом случае вы получаете System.IO.IOException от объекта NetworkStream. Это исключение имеет вложенный System.Net.Sockets.SocketException с ErrorCode из 10054 (SocketErrorCode == ConnectionReset). Для обработки исключения используйте блок try-catch. Например,

using System; 
using System.IO; 
using System.Net.Sockets; 

stream = client.GetStream(); 
new Thread(() => 
    { 
     try 
     { 
      while ((i = stream.Read(datalength, 0, 4)) != 0) 
      { 
       byte[] data = new byte[BitConverter.ToInt32(datalength, 0)]; 
       stream.Read(data, 0, data.Length); 
       this.Invoke((MethodInvoker)delegate 
       { 
        txtLog.Text += System.Environment.NewLine + "Server : " + Encoding.Default.GetString(data); 
       }); 
      } 
     } 
     catch (IOException ioex) 
     { 
      if (ioex.InnerException != null) 
      { 
       var sex = ex.InnerException as SocketException; 
       if (sex == null) 
       { 
        txtLog.Text += Environment.NewLine + "An unknown exception occurred."; 
       } 
       else 
       { 
        switch (sex.SocketErrorCode) 
        { 
         case SocketError.ConnectionReset: 
          txtLog.Text += Environment.NewLine + "A ConnectionReset SocketException occurred." 
          break; 
         default: 
          txtLog.Text += Environment.NewLine + "A SocketException occurred."; 
          break; 
        } 
       } 
      } 
      else 
      { 
       txtLog.Text += Environment.NewLine + "An IOException occurred."; 
      } 
     } 
    }).Start(); 
+0

, когда я начал соединение и прекратил работу с клиентом, я получил эту ошибку на стороне сервера в «случае SocketError.ConnectionReset: txtLog.Text + = Environment.NewLine +« произошло событие ConnectionReset SocketException »; break; ' Неверная операция поперечного потока: Control 'txtLog' обращается из потока, отличного от потока, на котором он был создан. –

+0

Элементы управления могут быть доступны только в потоке, на котором они созданы. Я не связывал связь с 'txtLog' как элементом управления. Добавление к нему в анонимном делете потока является источником проблемы. Дайте мне минутку, чтобы найти сообщение SO, посвященное этой проблеме. –

+0

http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c?rq=1 –

Смежные вопросы