我正在尝试为我的项目实现异步套接字。这是代码
public void Start(int listeningPort)
{
var ipHostInfo = Dns.Resolve(Dns.GetHostName());
var ipAddress = ipHostInfo.AddressList[0];
var localEndPoint = new IPEndPoint(ipAddress, listeningPort);
_listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_listener.Bind(localEndPoint);
_listener.Listen(3000);
Started = true;
Task.Factory.StartNew(() =>
{
while (Started)
{
allDone.Reset();
_listener.BeginAccept(AcceptCallback, _listener);
allDone.WaitOne();
}
});
}
public void Stop()
{
Started = false;
_listener.Shutdown(SocketShutdown.Both); //<-- throws SocketException
_listener.Close(2000);
_listener = null;
}
public void Kick(IClient client)
{
try
{
Clients.Remove(client);
client.Socket.Shutdown(SocketShutdown.Both);
client.Socket.Close();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
private void AcceptCallback(IAsyncResult ar)
{
Socket handler = null;
try
{
allDone.Set();
var listener = (Socket) ar.AsyncState;
handler = listener.EndAccept(ar);
var client = new Client(this, handler);
Clients.Add(client);
var state = new StateObject();
state.Socket = handler;
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
var client = ClientBySocket(handler);
if(handler != null && client != null) Kick(client);
}
}
private void ReadCallback(IAsyncResult ar)
{
Socket handler = null;
try
{
var state = (StateObject) ar.AsyncState;
handler = state.Socket;
var bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
if (Received != null)
{
var buff = new byte[bytesRead];
if (buff[0] == 0)
{
Stop();
}
return;
Array.Copy(state.Buffer, buff, bytesRead);
Debug.WriteLine(Encoding.UTF8.GetString(buff));
try
{
Received(this, new ReceiveArgs(buff));
}
catch(Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
handler.BeginReceive(state.Buffer, 0, StateObject.BufferSize, 0, ReadCallback, state);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
var client = ClientBySocket(handler);
if (handler != null && client != null) Kick(client);
}
}
但每次我调用 Stop(依次调用 shutdown)(无论客户端是否连接),Socket.Shutdown 都会抛出带有消息的 SocketException
Additional information: A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied
我真的被困在这里了。有人知道我做错了什么吗?
最佳答案
您的监听套接字未连接。我认为这条消息说得很好。每次接受连接时,您都会得到一个独立的新套接字。原始套接字从未连接到任何东西。
只是不要对其调用 Shutdown。
顺便说一句,您的 Accept 循环正在使用异步 IO,然后等待它完成。这是没有意义的。使用同步版本。
关于c# - Socket.Shutdown 抛出 SocketException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23963359/