同步套接字:ReceiveTimeout
Synchronous Socket: ReceiveTimeout
我有一个在读取时阻塞的套接字线程。我将套接字上的接收超时设置为 30 秒;如果没有读取到字节,则读取进入 IO 异常(内部异常:错误代码:10060)。我结束进程并关闭流并将线程设置为空。出于某种原因,我似乎无法关闭套接字连接。我不确定错误在哪里。下面是我的代码:
public class SampleClientSocket
{
private Socket cltSocket = null;
private volatile bool readyToRecv = false;
NetworkStream ns;
BinaryReader br;
BinaryWriter wr;
private string _caller = "SampleSocketClient";
Thread workerThread;
static void Main(string[] args)
{
BeginWork();
}
public void BeginWork()
{
try
{
IPEndPoint ipe = new IPEndPoint("127.0.0.1", 5000);
cltSocket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
cltSocket.Connect(ipe);
cltSocket.ReceiveTimeout = 30000;
cltSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
workerThread = new Thread(doWork_01);
workerThread.Start();
readyToRecv = true;
}
catch (Exception f)
{
Console.WriteLine(this._caller + f.StackTrace);
}
}
private void doWork_01()
{
try
{
this.ns = new NetworkStream(this.cltSocket);
this.br = new BinaryReader(this.ns);
this.wr = new BinaryWriter(this.ns);
readyToRecv = true;
this._lastSocketRead = toUnixTime(DateTime.Now);
}
catch
{
Console.WriteLine(this._caller + "ERROR OPENING STREAMS.");
readyToRecv = false;
}
while (this.readyToRecv)
{
bool _etxEncountered = false;
MemoryStream currentMessage = new MemoryStream();
byte buf = (byte)0;
while (!_etxEncountered)
{
try
{
buf = this.br.ReadByte();
}
catch (EndOfStreamException)
{
Console.WriteLine(this._caller + "ERROR: END OF STREAM");
readyToRecv = false;
_etxEncountered = true;
break;
}
catch (ObjectDisposedException)
{
Console.WriteLine(this._caller + "ERROR: Stream is closed!");
readyToRecv = false;
_etxEncountered = true;
break;
}
catch (IOException i)
{
Console.WriteLine(this._caller + "ERRORSTACK: IOException!" + i.StackTrace);
//if the ReeceiveTimeout is reached an IOException will be raised...
/// with an InnerException of type SocketException an ErrorCode 10060
var socketExpert = i.InnerException as SocketException;
if (socketExpert.ErrorCode != 10060)
{
Console.WriteLine(this._caller + "ERROR: IOException!" + socketExpert.ErrorCode);
readyToRecv = false;
_etxEncountered = true;
}
else
{
Console.WriteLine(this._caller + "Read: IOException for timeout! NOT DISCONNECTING");
readyToRecv = false;
_etxEncountered = true;
break;
}
}
catch (Exception f)
{
Console.WriteLine(this._caller + "Unknown exception" + f.StackTrace);
var socketExpert = f.InnerException as SocketException;
Console.WriteLine(this._caller + "Error code number: " + socketExpert.ErrorCode);
readyToRecv = false;
_etxEncountered = true;
}
if (buf.Equals(0x03) == true)
{
_etxEncountered = true;
break;
}
else if (buf.Equals(0x02) == false)
{
try
{
currentMessage.WriteByte(buf);
}
catch (Exception)
{
}
}
}
try { Thread.Sleep(10); }
catch { }
} // end while
EndWork();
}
public void EndWork()
{
try
{
readyToRecv = false;
//close streams
this.br.BaseStream.Flush();
this.br.Close();
this.br.Dispose();
this.wr.Flush();
this.wr.Close();
this.wr.Dispose();
this.ns.Flush();
this.ns.Close();
this.ns.Dispose();
this.cltSocket.Shutdown(SocketShutdown.Both);
//this.cltSocket.Disconnect(true);
this.cltSocket.Close();
this.cltSocket.Dispose();
this.cltSocket = null;
Console.WriteLine(this._caller + "GOODBYE...");
try
{
this.workerThread.Join(1000);
if (this.workerThread.IsAlive)
{
this.workerThread.Abort();
}
}
catch { }
this.workerThread = null;
}
catch
{
this.readyToRecv = false;
this.workerThread = null;
}
return;
}
}
感谢任何帮助。
这段代码似乎有很多问题。
我认为问题的原因是您试图在工作线程上加入工作线程。 doWork_01
在工作线程上是 运行,因此 EndWork
在工作线程上也会 运行。这相当于调用 Thread.CurrentThread.Join()
,并且只会死锁。此死锁可能会使您的进程保持活动状态,并可能导致诸如不释放套接字之类的问题。
我看不出有什么理由在这里尝试使用多线程。原始线程只是启动 worker,什么都不做。我建议删除所有线程,只使用套接字的局部变量,并使用 using
确保它被处理。
要正确退出进程,请使用 Environment.Exit(0);
、Application.Exit
或仅使用 Main 中的 return。
我有一个线程没有达到 Socket.Shutdown 和 socket.close。谢谢 jdweng 指给我看。
我有一个在读取时阻塞的套接字线程。我将套接字上的接收超时设置为 30 秒;如果没有读取到字节,则读取进入 IO 异常(内部异常:错误代码:10060)。我结束进程并关闭流并将线程设置为空。出于某种原因,我似乎无法关闭套接字连接。我不确定错误在哪里。下面是我的代码:
public class SampleClientSocket
{
private Socket cltSocket = null;
private volatile bool readyToRecv = false;
NetworkStream ns;
BinaryReader br;
BinaryWriter wr;
private string _caller = "SampleSocketClient";
Thread workerThread;
static void Main(string[] args)
{
BeginWork();
}
public void BeginWork()
{
try
{
IPEndPoint ipe = new IPEndPoint("127.0.0.1", 5000);
cltSocket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
cltSocket.Connect(ipe);
cltSocket.ReceiveTimeout = 30000;
cltSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
workerThread = new Thread(doWork_01);
workerThread.Start();
readyToRecv = true;
}
catch (Exception f)
{
Console.WriteLine(this._caller + f.StackTrace);
}
}
private void doWork_01()
{
try
{
this.ns = new NetworkStream(this.cltSocket);
this.br = new BinaryReader(this.ns);
this.wr = new BinaryWriter(this.ns);
readyToRecv = true;
this._lastSocketRead = toUnixTime(DateTime.Now);
}
catch
{
Console.WriteLine(this._caller + "ERROR OPENING STREAMS.");
readyToRecv = false;
}
while (this.readyToRecv)
{
bool _etxEncountered = false;
MemoryStream currentMessage = new MemoryStream();
byte buf = (byte)0;
while (!_etxEncountered)
{
try
{
buf = this.br.ReadByte();
}
catch (EndOfStreamException)
{
Console.WriteLine(this._caller + "ERROR: END OF STREAM");
readyToRecv = false;
_etxEncountered = true;
break;
}
catch (ObjectDisposedException)
{
Console.WriteLine(this._caller + "ERROR: Stream is closed!");
readyToRecv = false;
_etxEncountered = true;
break;
}
catch (IOException i)
{
Console.WriteLine(this._caller + "ERRORSTACK: IOException!" + i.StackTrace);
//if the ReeceiveTimeout is reached an IOException will be raised...
/// with an InnerException of type SocketException an ErrorCode 10060
var socketExpert = i.InnerException as SocketException;
if (socketExpert.ErrorCode != 10060)
{
Console.WriteLine(this._caller + "ERROR: IOException!" + socketExpert.ErrorCode);
readyToRecv = false;
_etxEncountered = true;
}
else
{
Console.WriteLine(this._caller + "Read: IOException for timeout! NOT DISCONNECTING");
readyToRecv = false;
_etxEncountered = true;
break;
}
}
catch (Exception f)
{
Console.WriteLine(this._caller + "Unknown exception" + f.StackTrace);
var socketExpert = f.InnerException as SocketException;
Console.WriteLine(this._caller + "Error code number: " + socketExpert.ErrorCode);
readyToRecv = false;
_etxEncountered = true;
}
if (buf.Equals(0x03) == true)
{
_etxEncountered = true;
break;
}
else if (buf.Equals(0x02) == false)
{
try
{
currentMessage.WriteByte(buf);
}
catch (Exception)
{
}
}
}
try { Thread.Sleep(10); }
catch { }
} // end while
EndWork();
}
public void EndWork()
{
try
{
readyToRecv = false;
//close streams
this.br.BaseStream.Flush();
this.br.Close();
this.br.Dispose();
this.wr.Flush();
this.wr.Close();
this.wr.Dispose();
this.ns.Flush();
this.ns.Close();
this.ns.Dispose();
this.cltSocket.Shutdown(SocketShutdown.Both);
//this.cltSocket.Disconnect(true);
this.cltSocket.Close();
this.cltSocket.Dispose();
this.cltSocket = null;
Console.WriteLine(this._caller + "GOODBYE...");
try
{
this.workerThread.Join(1000);
if (this.workerThread.IsAlive)
{
this.workerThread.Abort();
}
}
catch { }
this.workerThread = null;
}
catch
{
this.readyToRecv = false;
this.workerThread = null;
}
return;
}
}
感谢任何帮助。
这段代码似乎有很多问题。
我认为问题的原因是您试图在工作线程上加入工作线程。 doWork_01
在工作线程上是 运行,因此 EndWork
在工作线程上也会 运行。这相当于调用 Thread.CurrentThread.Join()
,并且只会死锁。此死锁可能会使您的进程保持活动状态,并可能导致诸如不释放套接字之类的问题。
我看不出有什么理由在这里尝试使用多线程。原始线程只是启动 worker,什么都不做。我建议删除所有线程,只使用套接字的局部变量,并使用 using
确保它被处理。
要正确退出进程,请使用 Environment.Exit(0);
、Application.Exit
或仅使用 Main 中的 return。
我有一个线程没有达到 Socket.Shutdown 和 socket.close。谢谢 jdweng 指给我看。