C # Socket.Receive comprimento da mensagem
No momento, estou desenvolvendo um servidor C # Socket que pode aceitar várias conexões de vários computadores clientes. O objetivo do servidor é permitir que os clientes "inscrevam-se" e "cancelem a inscrição" nos eventos do servido
Até agora, dei uma boa olhada aqui:http: //msdn.microsoft.com/en-us/library/5w7b7x5f (v = VS.100) .aspx ehttp: //msdn.microsoft.com/en-us/library/fx6588te.asp para idéias.
Todas as mensagens enviadas são criptografadas; portanto, pego a string que desejo enviar, converto-a em uma matriz de bytes [] e, em seguida, criptografamos os dados antes de pré-pendurar o comprimento da mensagem nos dados e enviá-los pelo conexão
Uma coisa que me parece um problema é a seguinte: no lado de recebimento, parece possível que Socket.EndReceive () (ou o retorno de chamada associado) possa retornar quando apenas metade da mensagem for recebida. Existe uma maneira fácil de garantir que cada mensagem seja recebida "concluída" e apenas uma mensagem por vez?
EDITAR Por exemplo, acho que os soquetes .NET / Windows não "encapsulam" as mensagens para garantir que uma única mensagem enviada com Socket.Send () seja recebida em uma chamada Socket.Receive ()? Ou faz?
inha implementação até agora:
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);
}
}