Я использую пример сервера MSDN, найденный здесь
И моя проблема в том, что этот код постоянно принимает только новых клиентов. Я хочу, чтобы он постоянно получал от всех клиентов, которых он также принимает. Этот код принимает клиента, затем получает от него одно сообщение, а затем отправляет одно сообщение, и все. Единственное, что я могу придумать, - это вставить метод асинхронного приема в цикл while (true), но это звучит неправильно.
Я немного изменил пример, но он по-прежнему имеет те же базовые функции.
public class AServer
{
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
Socket listener;
ArrayList clients;
public AServer(int port)
{
// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.IPv6Any, port);
clients = new ArrayList();
// Create a TCP/IP socket.
listener = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
listener.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, 0);
listener.Bind(localEndPoint);
listener.Listen(100);
}
public void ServerLoop(){
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();
}
}
public void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
ClientData state = new ClientData();
state.workSocket = handler;
clients.Add(state);
handler.BeginReceive(state.buffer, 0, ClientData.BufferSize, 0,new AsyncCallback(ReadCallback), state);
Console.WriteLine("we passed handler.BeginReceive");
}
public void ReadCallback(IAsyncResult ar)
{
// Retrieve the state object and the handler socket
// from the asynchronous state object.
ClientData data = (ClientData)ar.AsyncState;
String buff = String.Empty;
Socket handler = data.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
buff = Encoding.ASCII.GetString(data.buffer, 0, bytesRead);
ParseBuffer(buff);
Send(handler, "1");
}
if (bytesRead == 0) {
CloseConnection(handler);
}
}
private bool ParseBuffer(String buff) {
Console.WriteLine(buff);
switch (buff[0]) {
case '0':
break;
case '1':
break;
}
return true;
}
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
// Retrieve the socket from the state object.
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = handler.EndSend(ar);
}
private static void CloseConnection(Socket handler)
{
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
Конечно, мой основной метод просто последовательно вызывает конструктор, а затем цикл. Arraylist - это остаток некоторых моих попыток разобраться в этом.
Редактировать
Я искал те же функции, которые Select предлагает мне в C, но, очевидно, C # может делать то же самое с событиями.
1 ответ
В вашем ReadCallback
вам нужно снова отправить асинхронный Receive
:
public void ReadCallback(IAsyncResult ar)
{
// Retrieve the state object and the handler socket
// from the asynchronous state object.
ClientData data = (ClientData)ar.AsyncState;
String buff = String.Empty;
Socket handler = data.workSocket;
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
buff = Encoding.ASCII.GetString(data.buffer, 0, bytesRead);
ParseBuffer(buff);
Send(handler, "1");
// Here, you need to Receive again
handler.BeginReceive(state.buffer, 0, ClientData.BufferSize, 0,new AsyncCallback(ReadCallback), state);
}
if (bytesRead == 0) {
CloseConnection(handler);
}
}
Таким образом вы будете получать, отправлять, получать, отправлять, получать, отправлять и т. Д. На каждом сокете. Вам нужна обработка ошибок, и правильный сервер должен будет обрабатывать неполные сообщения, но это общая идея.
Кстати, аналогично вы должны опубликовать еще один асинхронный Accept в своем обратном вызове accept:
public void AcceptCallback(IAsyncResult ar)
{
// Signal the main thread to continue.
allDone.Set();
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
ClientData state = new ClientData();
state.workSocket = handler;
clients.Add(state);
handler.BeginReceive(state.buffer, 0, ClientData.BufferSize, 0,new AsyncCallback(ReadCallback), state);
Console.WriteLine("we passed handler.BeginReceive");
// Here, you must start a new accept:
listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
}
Похожие вопросы
Новые вопросы
c#
C# (произносится как «see Sharp») — это высокоуровневый мультипарадигменный язык программирования со статической типизацией, разработанный Microsoft. Код C# обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, которое включает в себя .NET, .NET Framework, .NET MAUI и Xamarin среди прочих. Используйте этот тег для ответов на вопросы о коде, написанном на C#, или о формальной спецификации C#.