C#Socket服务端使用SocketAsyncEventArgs示例代码
时间: 2023-12-07 11:12:39 浏览: 144
好的,下面是一个简单的C# Socket服务端使用SocketAsyncEventArgs的示例代码:
```csharp
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public class SocketServer
{
private Socket m_serverSocket;
private Semaphore m_maxAcceptedClients;
private SocketAsyncEventArgsPool m_readWritePool;
public SocketServer(int maxConnections)
{
m_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_serverSocket.Bind(new IPEndPoint(IPAddress.Any, 1234));
m_serverSocket.Listen(maxConnections);
m_maxAcceptedClients = new Semaphore(maxConnections, maxConnections);
m_readWritePool = new SocketAsyncEventArgsPool(maxConnections);
for (int i = 0; i < maxConnections; i++)
{
SocketAsyncEventArgs readEventArgs = new SocketAsyncEventArgs();
readEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
readEventArgs.UserToken = new AsyncUserToken();
m_readWritePool.Push(readEventArgs);
}
}
public void Start()
{
StartAccept(null);
}
private void StartAccept(SocketAsyncEventArgs acceptEventArgs)
{
if (acceptEventArgs == null)
{
acceptEventArgs = new SocketAsyncEventArgs();
acceptEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(Accept_Completed);
}
else
{
acceptEventArgs.AcceptSocket = null;
}
m_maxAcceptedClients.WaitOne();
if (!m_serverSocket.AcceptAsync(acceptEventArgs))
{
ProcessAccept(acceptEventArgs);
}
}
private void ProcessAccept(SocketAsyncEventArgs acceptEventArgs)
{
SocketAsyncEventArgs readEventArgs = m_readWritePool.Pop();
AsyncUserToken userToken = (AsyncUserToken)readEventArgs.UserToken;
userToken.Socket = acceptEventArgs.AcceptSocket;
userToken.ReadEventArgs = readEventArgs;
readEventArgs.AcceptSocket = userToken.Socket;
if (!userToken.Socket.ReceiveAsync(readEventArgs))
{
ProcessReceive(readEventArgs);
}
StartAccept(acceptEventArgs);
}
private void Accept_Completed(object sender, SocketAsyncEventArgs e)
{
ProcessAccept(e);
}
private void IO_Completed(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
ProcessReceive(e);
break;
case SocketAsyncOperation.Send:
ProcessSend(e);
break;
default:
throw new ArgumentException("The last operation completed on the socket was not a receive or send");
}
}
private void ProcessReceive(SocketAsyncEventArgs e)
{
AsyncUserToken userToken = (AsyncUserToken)e.UserToken;
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
{
userToken.Data.AddRange(e.Buffer.Take(e.BytesTransferred));
if (userToken.Data.Count >= 4)
{
int len = BitConverter.ToInt32(userToken.Data.Take(4).ToArray(), 0);
if (userToken.Data.Count >= 4 + len)
{
byte[] buffer = userToken.Data.Skip(4).Take(len).ToArray();
userToken.Data.RemoveRange(0, 4 + len);
// 处理请求并响应
byte[] response = HandleRequest(buffer);
Send(userToken.Socket, response);
return;
}
}
if (!userToken.Socket.ReceiveAsync(e))
{
ProcessReceive(e);
}
}
else
{
CloseClientSocket(userToken);
}
}
private void ProcessSend(SocketAsyncEventArgs e)
{
AsyncUserToken userToken = (AsyncUserToken)e.UserToken;
if (e.SocketError == SocketError.Success)
{
if (!userToken.Socket.ReceiveAsync(userToken.ReadEventArgs))
{
ProcessReceive(userToken.ReadEventArgs);
}
}
else
{
CloseClientSocket(userToken);
}
}
private void Send(Socket socket, byte[] buffer)
{
SocketAsyncEventArgs sendEventArgs = new SocketAsyncEventArgs();
sendEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
sendEventArgs.SetBuffer(buffer, 0, buffer.Length);
sendEventArgs.UserToken = socket;
if (!socket.SendAsync(sendEventArgs))
{
ProcessSend(sendEventArgs);
}
}
private void CloseClientSocket(AsyncUserToken userToken)
{
try
{
userToken.Socket.Shutdown(SocketShutdown.Send);
}
catch (Exception) { }
userToken.Socket.Close();
m_readWritePool.Push(userToken.ReadEventArgs);
m_maxAcceptedClients.Release();
}
private byte[] HandleRequest(byte[] request)
{
// 处理请求并响应
return null;
}
}
public class AsyncUserToken
{
public Socket Socket { get; set; }
public List<byte> Data { get; set; }
public SocketAsyncEventArgs ReadEventArgs { get; set; }
public AsyncUserToken()
{
Data = new List<byte>();
}
}
```
以上示例代码演示了如何使用SocketAsyncEventArgs实现一个简单的Socket服务端,其中包含了异步接收、异步发送和连接池等功能。当有客户端连接时,它会从连接池中获取一个SocketAsyncEventArgs对象,并使用它来进行通信。在通信完成后,它会将SocketAsyncEventArgs对象放回连接池中,以便于重用。
阅读全文