我正在尝试在多线程环境中创建异步套接字客户端,但它无法正常工作。 如下面的示例代码, 如果我创建新的AsyncSocketClient并从多线程环境调用StartClent,它将只处理一个或两个休息,它不处理。(我正在为每个新请求创建新的AsyncSocketClient) 是因为静态变量,
class AsyncSocketClient
{
private static AutoResetEvent sendDone =
new AutoResetEvent(false);
private static AutoResetEvent receiveDone =
new AutoResetEvent(false);
private static ManualResetEvent connectDone =
new ManualResetEvent(false);
static private String response = "";
public void StartClent()
{
Socket workSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// clientSock.ReceiveTimeout = 1;
try
{
workSocket.BeginConnect(new IPEndPoint(IPAddress.Loopback, 8080), new AsyncCallback(ConnectCallBack), workSocket);
connectDone.WaitOne();
Send(s.workSocket, "<EOF>");
sendDone.WaitOne();
Receive(workSocket);
receiveDone.WaitOne();
}
catch(Exception ex)
{
}
}
private void ConnectCallBack(IAsyncResult ar)
{
Socket workSocket = (Socket)ar.AsyncState;
workSocket.EndConnect(ar);
connectDone.Set();
}
private void Receive(Socket client)
{
StateObject state = new StateObject();
state.workSocket = client;
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallBack), state);
}
private void ReceiveCallBack(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
int byteReceived= client.EndReceive(ar);
if (byteReceived > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, state.buffer.Length));
Array.Clear(state.buffer, 0, state.buffer.Length);
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallBack), state);
}
else
{
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
receiveDone.Set();
}
}
private void Send(Socket client,string data)
{
byte[] sendBufer = Encoding.ASCII.GetBytes(data);
client.BeginSend(sendBufer, 0, sendBufer.Length, 0, new AsyncCallback(BeginSendCallBack), client);
}
private void BeginSendCallBack(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState;
int byteSent= client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", byteSent);
sendDone.Set();
}
}
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 30;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
答案 0 :(得分:0)
以下是一个非阻塞客户端和服务器的示例,其中实现了简单的回显。没有错误检查,没有正确关闭,应该做什么。服务器有一些同步代码,只是为了让它更容易理解。
客户
public class AsyncClient
{
private const int Port = 9999;
private readonly string _clientId;
private readonly Random _random;
public AsyncClient(int clientId)
{
_clientId = string.Format("Client Id: {0}", clientId);
_random = new Random(clientId);
}
public void StartClient()
{
try
{
var workSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var state = new ClientState { WorkSocket = workSocket };
workSocket.BeginConnect(new IPEndPoint(IPAddress.Loopback, Port), ConnectCallBack, state);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private void ConnectCallBack(IAsyncResult ar)
{
var state = (ClientState) ar.AsyncState;
state.WorkSocket.EndConnect(ar);
Send(state);
}
private void Receive(ClientState clientState)
{
clientState.WorkSocket.BeginReceive(clientState.Buffer, 0, ClientState.BufferSize, 0, ReceiveCallBack, clientState);
}
private void ReceiveCallBack(IAsyncResult ar)
{
var state = (ClientState) ar.AsyncState;
Socket client = state.WorkSocket;
int byteReceived= client.EndReceive(ar);
if (byteReceived > 0)
{
var receivedString = Encoding.UTF8.GetString(state.Buffer, 0, byteReceived);
Console.WriteLine("From Server: " + receivedString);
Array.Clear(state.Buffer, 0, state.Buffer.Length);
state.Count++;
Thread.Sleep(1000 + _random.Next(2000));
Send(state);
}
}
private void Send(ClientState clientState)
{
Console.WriteLine("Sending " + _clientId);
byte[] buffer = Encoding.UTF8.GetBytes(string.Format("Send from Thread {0} Client id {1} Count {2}", Thread.CurrentThread.ManagedThreadId, _clientId,clientState.Count));
clientState.WorkSocket.BeginSend(buffer, 0, buffer.Length, 0, BeginSendCallBack, clientState);
}
private void BeginSendCallBack(IAsyncResult ar)
{
var state = (ClientState) ar.AsyncState;
int byteSent= state.WorkSocket.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", byteSent);
Receive(state);
}
}
public class ClientState
{
// Client socket.
public Socket WorkSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] Buffer = new byte[BufferSize];
public int Count = 0;
}
服务器
public class AsyncServer
{
private const int Port = 9999;
public void StartServer()
{
var thread = new Thread(Run) {IsBackground = true};
thread.Start();
}
private void Run()
{
Console.WriteLine("Running");
var tcpListener = new TcpListener(IPAddress.Loopback, Port);
tcpListener.Start();
while (true)
{
Console.WriteLine("Before Accept");
var state = new ServerState {WorkSocket = tcpListener.AcceptSocket()};
Console.WriteLine("Before Recieve");
Receive(state);
}
}
private void Receive(ServerState state)
{
state.WorkSocket.BeginReceive(state.Buffer, 0, ServerState.BufferSize, 0, ReceiveCallBack, state);
}
private void ReceiveCallBack(IAsyncResult ar)
{
Console.WriteLine("ReceiveCallBack");
var state = (ServerState) ar.AsyncState;
try
{
int byteReceived= state.WorkSocket.EndReceive(ar);
if (byteReceived > 0)
{
var receivedString = Encoding.UTF8.GetString(state.Buffer, 0, byteReceived);
Console.WriteLine("Received: " + receivedString);
var bytesToSend = Encoding.UTF8.GetBytes("Server Got --> " + receivedString);
Array.Copy(bytesToSend, state.Buffer, bytesToSend.Length);
state.WorkSocket.Send(state.Buffer, 0, bytesToSend.Length, SocketFlags.None);
Array.Clear(state.Buffer, 0, state.Buffer.Length);
Receive(state);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private class ServerState
{
public const int BufferSize = 1024;
public readonly byte[] Buffer = new byte[1024];
public Socket WorkSocket;
}
我使用控制台运行此操作,您可以拥有两个应用程序,也可以单独启动客户端和服务器。
static void Main(string[] args)
{
if (args.Length != 0)
{
var server = new AsyncServer();
server.StartServer();
}
else
{
for(int i = 0; i < 10; i++)
{
var client = new AsyncClient(i);
client.StartClient();
}
}
Console.WriteLine("Press a key to exit");
Console.ReadKey();
}