C# сокет обмена сообщениями клиент-сервер - PullRequest
0 голосов
/ 11 марта 2020

Я установил систему чата клиент-сервер. Это будет работать на разных компьютерах. В данный момент я тестирую, и поэтому клиент и сервер находятся на моем локальном хосте. В данный момент я сосредотачиваюсь на приеме клиента (с 8192-байтовым буфером), потому что проблема заключается в том, что проблема сохраняется. И проблема в том, что когда вы вводите команду с очень коротким текстом (здесь 123):

Сервер SHORT_COMMAND 123% ---> Клиент SHORT_COMMAND 123%

, но когда я выдаю очень длинную команду (24k) каждая партия поступает не в правильном порядке. Например, представьте очень длинный текст 111 ..... 11112222 .... 2222333 .... 33334444 .... 4444 LONG_COMMAND 111 .... 3333% поэтому автоматически режется на

LONG_COMMAND 111 .... 1111 2222 .... 2222 3333 ... 3333 4444 ... 4444% и отправляется в таком порядке

, что не так прием и что может случиться, это получить

LONG_COMMAND 111 .... 1111 2222 .... 2222 4444 ... 4444% 3333 ... 3333

, или это может смешаться с другие короткие команды, такие как

LONG_COMMAND 111 .... 1111 2222 .... 2222 SHORT_COMMAND 123% 3333 ... 3333 4444 ... 4444%

Учтите, что некоторые сообщения могут отправлять очень быстро один за другим.

Спасибо за ЛЮБУЮ помощь

Патрик


Код клиента

Я запускаю клиента с помощью следующей процедуры. В моем случае я передаю -1

public static bool StartClient(string strIpAddress, string strPort)
{
    // Connect to a remote device.
    try
    {
        if (strIpAddress.Trim() == "-1")
            strIpAddress = GetLocalIPAddress();

        IPAddress ipAddress = IPAddress.Parse(strIpAddress);
        int port = int.Parse(strPort);
        IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
        socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) { NoDelay = true };
        socketClient.BeginConnect(remoteEP, new AsyncCallback(ConnectClientCallback), socketClient);
        OnNotification_Client?.Invoke(eSocketOperation.CONNECT, "Client connected to " + strIpAddress + " port=" + strPort, eSocketOperationResultType.SUCCESS);
        ReceiveClient();
        return true;
    }
    catch (Exception e)
    {
        MessageBox.Show("StartClient exc:" + e.ToString());
        return false;
    }
}

, затем

private static void ConnectClientCallback(IAsyncResult ar)
{
    try
    {
        socketClient = (Socket)ar.AsyncState;
        socketClient.EndConnect(ar);
    }
    catch (Exception e)
    {
        MessageBox.Show(e.ToString());
    }
}

Следующая часть - это прием с:

public static void ReceiveClient()
{
    try
    {
        StateObject state = new StateObject();
        state.workSocket = socketClient;
        socketClient.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback_Client), state);
    }
    catch (Exception e)
    {
        MessageBox.Show(e.ToString(), "ReceiveClient", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}

наконец

private static void ReceiveCallback_Client(IAsyncResult ar)
{

    try
    {
        StateObject state = (StateObject)ar.AsyncState;
        Socket client = state.workSocket;
        if (!client.Connected)
            return;
        int bytesRead = client.EndReceive(ar);

        if (bytesRead > 0)
        {
            string message = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
            if (message == null)
                OnNotification_Client?.Invoke(eSocketOperationResultType.ERROR, "Received null message from server", eSocketOperationResultType.ERROR);
            else
            {

                strReceivedMessageClient += message;
                if (strReceivedMessageClient.EndsWith(StateObject.CONFIRMATION.ToString()))
                {
                    ...


Код сервера

Сервер запущен с

public static void StartServer(string _strPort)
{
    Serializers.Logger.WriteLog("StartServer");
    StrPort = _strPort;

    // Data buffer for incoming data.
    byte[] bytes = new Byte[BufferSize];

    IPAddress ipAddress = IPAddress.Parse(GetLocalIPAddress());
    int port = int.Parse(_strPort);
    IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);

    if (listener == null)
        listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    try
    {
        listener.Bind(localEndPoint);
        listener.Listen(100);
        OnNotification_Server?.Invoke("Waiting for a connection on " + ipAddress.ToString());
        listener.BeginAccept(new AsyncCallback(AcceptCallbackServer), listener);
    }
    catch (Exception e)
    {
        MessageBox.Show(e.ToString());
    }
}

Принять

public static void AcceptCallbackServer(IAsyncResult ar)
{
    if (listener == null)
        return;

    listener = (Socket)ar.AsyncState;
    Socket handler = listener.EndAccept(ar);
    StateObject state = new StateObject();
    state.workSocket = handler;
    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback_Server), state);
}

и последнее, но не менее важное: отправка:

public static void SendFromServerToClient(object command, String data, eSocketOperationResultType sort)
{
    string strMessage; ;
    strMessage = command.ToString() + '|' + data + '|' + sort + "%";

    byte[] byteData = Encoding.ASCII.GetBytes(strMessage);
    try
    {
        if (socketServer != null)
            socketServer.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), socketServer);
    }
    catch (Exception exc)
    {

    }
}

private static void SendCallback(IAsyncResult ar)
{
    try
    {
        Socket handler = (Socket)ar.AsyncState;
        int bytesSent = handler.EndSend(ar);
    }
    catch (Exception e)
    {
        MessageBox.Show(e.ToString());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...