今日研究socket通讯,应用情景是,一台服务器要链接多个终端设备。
其中服务器做server端,终端做client端,client需要长连接到server,如果中途通讯中断,server需要能够侦测到这个事件,释放连接资源。重新等待client的连接。
在网上参考了不少文章,其中有一篇文章的内容比较相符,不过这篇文章中的连接不是长连接。
稍作修改后,实现了异步 长连接 可以多终端同时通讯。
贴出代码如下:(代码中socket的释放是做了一个30秒的定时,可以替换成其他条件判断,在需要时释放资源)
代码结构很清晰,不做注释了。。
usingSystem;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
// State object for reading client dataasynchronously
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize =1024;
// Receive buffer.
public byte[] buffer = newbyte[BufferSize];
// Received data string.
public StringBuilder sb = newStringBuilder();
}
public class AsynchronousSocketListener
{
// Thread signal.
public static ManualResetEventallDone = new ManualResetEvent(false);
publicAsynchronousSocketListener()
{
}
public static void StartListening()
{
// Data buffer forincoming data.
byte[] bytes = newByte[1024];
// Establish thelocal endpoint for the socket.
// The DNS name ofthe computer
// running thelistener is "host.contoso.com".
// IPHostEntryipHostInfo = Dns.Resolve(Dns.GetHostName());
// IPAddressipAddress = ipHostInfo.AddressList[0];
IPAddress ipAddress= IPAddress.Any;
IPEndPointlocalEndPoint = new IPEndPoint(ipAddress, 13000);
// Create a TCP/IPsocket.
Socket listener =new Socket(AddressFamily.InterNetwork,
SocketType.Stream,ProtocolType.Tcp);
// Bind the socketto the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
while(true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
Console.WriteLine("Waiting for a connection...");
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
public static voidAcceptCallback(IAsyncResult ar)
{
int i = 0;
// Signal the mainthread to continue.
allDone.Set();
// Get the socketthat handles the client request.
Socket listener =(Socket)ar.AsyncState;
Socket handler =listener.EndAccept(ar);
// Create the stateobject.
StateObject state =new StateObject();
state.workSocket =handler;
while (true)
{
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
newAsyncCallback(ReadCallback), state);
Thread.Sleep(100);
i +=1;
//Socket will colse after 30 seconds
if(i>300)
{
handler.Shutdown(SocketShutdown.Both);
handler.Close();
break ;
}
}
}
public static voidReadCallback(IAsyncResult ar)
{
String content =String.Empty;
// Retrieve thestate object and the handler socket
// from theasynchronous state object.
StateObject state =(StateObject)ar.AsyncState;
Socket handler =state.workSocket;
// Read data fromthe client socket.
int bytesRead =handler.EndReceive(ar);
if (bytesRead >0)
{
//There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer, 0, bytesRead));
//Check for end-of-file tag. If it is not there, read
//more data.
content = state.sb.ToString();
if(content.IndexOf("<EOF>") > -1)
{
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content);
// Echo the data back to the client.
Send(handler, content);
}
else
{
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Sockethandler, String data)
{
// Convert thestring data to byte data using ASCII encoding.
byte[] byteData =Encoding.ASCII.GetBytes(data);
// Begin sending thedata to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
newAsyncCallback(SendCallback), handler);
}
private static voidSendCallback(IAsyncResult ar)
{
try
{
//Retrieve the socket from the state object.
Sockethandler = (Socket)ar.AsyncState;
//Complete sending the data to the remote device.
intbytesSent = handler.EndSend(ar);
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
//handler.Shutdown(SocketShutdown.Both);
//handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}