C # Socket.Receive message length

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);
    }         
}

7
задан Siyfion 24 March 2011 в 15:35
поделиться