从哪里出现这个问题?
SocketException无法执行套接字上的操作,因为系统缺少足够的缓冲区空间或者队列已满,
Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 50509);
EndPoint tmpRemote = (EndPoint)(sender);
newsock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
newsock.Bind(ipep);
while (thread_Listen == true && work == true)
{
try
{
Object state = new Object();
**>> at this place >>** newsock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref tmpRemote, new AsyncCallback(DoReceiveFrom), state);
Array.Clear(buffer, 0, buffer.Length);
}
catch (SocketException ex)
{
MessageBox.Show(ex.ToString());
}
}
func DoReceiveFrom 的方式如何
private void DoReceiveFrom(IAsyncResult iar)
{
try
{
Socket recvSock = (Socket)iar.AsyncState;
EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
int msgLen = recvSock.EndReceiveFrom(iar, ref clientEP);
byte[] localMsg = GetAndCleanPacket(buffer);
string[] packet = Encoding.ASCII.GetString(localMsg).Split(new Char[] { '|' });
if (packet.Length > 0)
{
if (packet[0] == "ms")
{
// Connect
if (packet[1] == "c") MSc(ip[0], packet[9], packet, clientEP);
else if (packet[1] == "s") MSs(ip[0], packet);
else if (packet[1] == "d") MDc(ip[0], packet);
}
else if (packet[0] == "p") ping(clientEP);
else if (packet[0] == "sList") serverList(clientEP);
else if (packet[0] == "bi") brGetInfo(packet, clientEP);
else if (packet[0] == "error") AddError(packet[1], packet[2]);
}
}
catch (InvalidOperationException)
{
}
catch (SocketException)
{
}
catch (Exception e)
{
errors.Add(e.ToString());
}
}
答案 0 :(得分:1)
你的while循环以非常高的速率调用BeginReceiveFrom()。在操作系统拔出插头并拒绝分配更多资源之前,不应该花费超过一秒的时间。
您必须以不同方式执行此操作,只有在收到某些内容后才会调用BeginReceiveFrom。在DoReceiveFrom()。
中答案 1 :(得分:0)
我所做的是使用包含“IAsyncResult”对象的“StateObject”类。这应该用于 TCP 和 UDP。这是 UDP 的示例。
// Used for receiver to signal client that data has been received
// 'readonly' for .Net 4.8
private readonly ManualResetEvent receiveDone = new ManualResetEvent(false);
/// <summary>
/// Supports async receive on UDP socket
/// </summary>
private class StateObject
{
// Client socket.
public UdpClient workSocket = null;
// Receive buffer.
public byte[] buffer;
// Received data string.
public StringBuilder sb = new StringBuilder();
//public int bytesRead;
// receiver state
public IAsyncResult result;
public delegate void RecvMethod(IAsyncResult result);
public void BeginReceive(RecvMethod recvMethod, UdpClient udpClient)
{
// Set the socket
workSocket = udpClient;
// start async receiver
result = workSocket.BeginReceive(new AsyncCallback(recvMethod), this);
}
}
“Receive”方法(由客户端应用程序调用)检查其状态,并且仅在接收器未发出信号(使用 receiveDone)且 IAsyncResult.Completed 为 false 时触发。
<块引用>这就是这里的关键:如果接收器仍然处于活动状态,请不要再次触发它,否则就是在浪费系统资源。它需要另一个套接字和缓冲内存空间,这会占用您的应用程序,通常是当您尝试与离线设备进行通信时。
/// <summary>
/// Set up async receive handler
/// </summary>
/// <returns></returns>
public void Receive()
{
// if receiver running, no packet received - do not restart receiver!
// did receiver signal done?
if (receiveDone.WaitOne(0))
{
// yes - do not restart receiver!
}
// is receiver still running?
else if (CurrentState.result != null && !CurrentState.result.IsCompleted)
{
// yes - do not restart receiver!
}
else
{
// Begin receiving the data from the remote device.
CurrentState.BeginReceive(ReceiveCallback, udpClient);
}
}
接收回调如下所示:
/// <summary>
/// End receive (with blocking) and process received data into buffer
/// </summary>
/// <param name="ar">Information about the async operation</param>
private void ReceiveCallback(IAsyncResult ar)
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject st = ar.AsyncState as StateObject;
UdpClient client = st.workSocket;
try
{
st.buffer = client.EndReceive(ar, ref receivePoint);
// Read data from the remote device.
receiveDone.Set();
}
// Since this is a callback, catch any error
// ObjectDisposedException has been seen
catch (ObjectDisposedException)
{ }
// "An existing connection was forcibly closed by remote host" has been seen
// see https://stackoverflow.com/questions/38191968/c-sharp-udp-an-existing-connection-was-forcibly-closed-by-the-remote-host for further information
catch
{
}
}