I ' m в настоящее время разрабатывает сервер C # Socket, который может принимать несколько подключений от нескольких клиентских компьютеров. Задача сервера - позволить клиентам «подписываться» и «отказываться от подписки» на серверные события.
До сих пор я хорошо рассмотрел здесь: http://msdn.microsoft. com / en-us / library / 5w7b7x5f (v = VS.100) .aspx и http://msdn.microsoft.com/en-us/library/fx6588te.aspx для идей.
Все сообщения, которые я отправляю, зашифрованы, поэтому я беру строковое сообщение, которое хочу отправить, конвертирую его в массив byte [], а затем шифрую данные перед тем, как отложить длину сообщения до данных и отправить их. по соединению.
Одна вещь, которая кажется мне проблемой, заключается в следующем: на принимающей стороне кажется возможным, что Socket. EndReceive () (или связанный с ним обратный вызов) может вернуться, когда получена только половина сообщения. Есть ли простой способ гарантировать, что каждое сообщение будет получено «полным» и только одно сообщение за раз?
РЕДАКТИРОВАТЬ: Например, я полагаю, что сокеты .NET / Windows не «переносят» сообщения, чтобы гарантировать что одно сообщение, отправленное с помощью Socket.Send (), получено за один вызов Socket.Receive ()? Или нет?
Моя реализация на данный момент:
private void StartListening()
{
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPEndPoint localEP = new IPEndPoint(ipHostInfo.AddressList[0], Constants.PortNumber);
Socket listener = new Socket(localEP.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(localEP);
listener.Listen(10);
while (true)
{
// Reset the event.
this.listenAllDone.Reset();
// Begin waiting for a connection
listener.BeginAccept(new AsyncCallback(this.AcceptCallback), listener);
// Wait for the event.
this.listenAllDone.WaitOne();
}
}
private void AcceptCallback(IAsyncResult ar)
{
// Get the socket that handles the client request.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Signal the main thread to continue.
this.listenAllDone.Set();
// Accept the incoming connection and save a reference to the new Socket in the client data.
CClient client = new CClient();
client.Socket = handler;
lock (this.clientList)
{
this.clientList.Add(client);
}
while (true)
{
this.readAllDone.Reset();
// Begin waiting on data from the client.
handler.BeginReceive(client.DataBuffer, 0, client.DataBuffer.Length, 0, new AsyncCallback(this.ReadCallback), client);
this.readAllDone.WaitOne();
}
}
private void ReadCallback(IAsyncResult asyn)
{
CClient theClient = (CClient)asyn.AsyncState;
// End the receive and get the number of bytes read.
int iRx = theClient.Socket.EndReceive(asyn);
if (iRx != 0)
{
// Data was read from the socket.
// So save the data
byte[] recievedMsg = new byte[iRx];
Array.Copy(theClient.DataBuffer, recievedMsg, iRx);
this.readAllDone.Set();
// Decode the message recieved and act accordingly.
theClient.DecodeAndProcessMessage(recievedMsg);
// Go back to waiting for data.
this.WaitForData(theClient);
}
}