我是TCP / IP编程的新手。我使用Microsoft文档和我在网上找到的一个例子创建了一个监听器。
我创建了一个使用本地IP侦听端口的程序。
当一条消息最终进入时,程序立即达到100%负载并停留在那里,不幸的是我不知道如何阻止它。我假设我必须使用ManualResetEvent
但是当我尝试实现此功能时,网页就不会加载。
我的实现如下:(如果有人想知道,端口是随机端口)
public static class Listener
{
private const int bufferSize = 2048;
private static byte[] buffer = new byte[bufferSize];
private static Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public static void StartListening()
{
//Gets local machine IP address
string ip = GetLocalIPAddress();
//Creates the IPADDRESS
IPAddress ipAddress = IPAddress.Parse(ip);
//Creates a local end point for .Bind(xxx)
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 1322);
Socket listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
//Binds to local machines IP with port 1322
listener.Bind(localEndPoint);
//Places socket in a listening state
listener.Listen(0);
listener.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
catch (Exception e)
{
//Throw exception
}
}
private static void CloseSocket()
{
listener.Shutdown(SocketShutdown.Both);
listener.Close();
}
public static void AcceptCallback(IAsyncResult ar)
{
//Socket casted to async state
Socket listenerSocket = (Socket)ar.AsyncState;
try
{
//Try end accept
listenerSocket = listener.EndAccept(ar);
}catch(Exception e)
{
//Throw exception
}
//Receive data
listenerSocket.BeginReceive(buffer, 0, bufferSize, SocketFlags.None, new AsyncCallback(ReadCallBack), listenerSocket);
listener.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
public static void ReadCallBack(IAsyncResult ar)
{
Socket listenerSocket = (Socket)ar.AsyncState;
int received = 0;
try
{
//Amount of bytes that has been sent
received = listenerSocket.EndReceive(ar);
}catch(Exception e)
{
listener.Close();
}
//Create byte array for encoding
byte[] bytes = new Byte[received];
Array.Copy(buffer,bytes,received);
string recievedMessage = Encoding.ASCII.GetString(bytes);
if (received > 0)
{
//do task input
System.Diagnostics.Debug.WriteLine(recievedMessage);
}
//work on this
listenerSocket.BeginReceive(buffer, 0 , bufferSize, SocketFlags.None, new AsyncCallback(ReadCallBack), listenerSocket);
}
private static string GetLocalIPAddress()
{
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
throw new Exception("Local IP Address Not Found!");
}
感谢您的帮助。
答案 0 :(得分:1)
您没有将侦听器套接字传递给BeginAccept。
listener.BeginAccept(new AsyncCallback(AcceptCallback), null);
和
Socket listenerSocket = (Socket)ar.AsyncState;
为什么要阅读Socket listenerSocket = (Socket)ar.AsyncState;
??
您在listenerSocket
方法中构建StartListening
,但您没有使用它。
当您关闭“监听器”(ServerClientSocket)时,您不应再次呼叫BeginReceive
。只需return
。
当套接字received == 0
关闭时,请勿启动BeginReceive
。这就是它永远循环的原因......开始/结束接收直接返回received
== 0
public static void ReadCallBack(IAsyncResult ar)
{
Socket listenerSocket = (Socket)ar.AsyncState;
int received = 0;
try
{
//Amount of bytes that has been sent
received = listenerSocket.EndReceive(ar);
}catch(Exception e)
{
received = 0;
}
if(received == 0)
{
listener.Close();
return;
}
//Create byte array for encoding
byte[] bytes = new Byte[received];
Array.Copy(buffer,bytes,received);
string recievedMessage = Encoding.ASCII.GetString(bytes);
if (received > 0)
{
//do task input
System.Diagnostics.Debug.WriteLine(recievedMessage);
}
//work on this
listenerSocket.BeginReceive(buffer, 0 , bufferSize, SocketFlags.None, new AsyncCallback(ReadCallBack), listenerSocket);
}
TCP / IP套接字是流式套接字,因此您永远不会知道您是否收到了完整的数据包,甚至是两个。您需要知道收到了完整的消息。经常使用PreLength协议。写一个表示后续数据量的值。
答案 1 :(得分:0)
我看到你传递0作为Socket.Listen方法的参数,不确定这是否是导致问题的原因,但是值得尝试将其更改为100
public void Listen(int backlog)
int backlog:挂起连接队列的最大长度。
msdn:https://msdn.microsoft.com/nl-nl/library/system.net.sockets.socket.listen(v=vs.110).aspx