소켓 통신을 하는데 있어서 너무 큰 메시지인 경우에 서버에서 한번에 데이터를 수신받지 못할 수 있습니다

 

문제 발생

클라이언트 측에서 7000 바이트가 넘는 데이터를 전송해야 하는 상황이 발생하였습니다.

 

해결 방법

서버 측에서는 큰 데이터를 한번에 받을 수 없기에 나눠서 받아 해당 데이터를 누적시켜 처리하는 방법을 선택해야 했습니다.

 

클라이언트 측에서는 데이터의 마지막 끝단에 개행 문자를 삽입하여 메시지의 끝을 서버가 알 수 있도록 하였으며

private func sendJSONMessage(_ message: SocketModel) {
    do {
        var data = try JSONEncoder().encode(message)
        if let newlineData = "\n".data(using: .utf8) {
            data.append(newlineData)
        }
        sendMessage(data)
    } catch {
        print("Failed to encode message: \(error)")
    }
}

 

서버 측에서는 데이터에 '\n' 개행문자가 존재하는지 여부를 확인하고 존재하면 누적된 데이터를 처리할 수 있도록 만들 수 있습니다. 

물론 개행문자가 아닌 특정 다른 문자열 또는 조건을 사용하여 문제를 해결할 수도 있습니다.
private static async Task HandleClientAsync(TcpClient client)
{
    var stream = client.GetStream();
    var buffer = new byte[1024];
    var receivedData = new List<byte>();

    try
    {
        while (client.Connected)
        {
            int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
            if (bytesRead == 0) break;

            receivedData.AddRange(buffer.Take(bytesRead));

            int newlineIndex;
            while ((newlineIndex = receivedData.IndexOf((byte)'\n')) != -1)
            {
                var messageBytes = receivedData.Take(newlineIndex).ToArray();
                receivedData.RemoveRange(0, newlineIndex + 1); 

                var message = Encoding.UTF8.GetString(messageBytes);
                Console.WriteLine($"Received from client: {message}");

                await HandleMessageAsync(client, message);
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error handling client: {ex.Message}");
    }
    finally
    {
        RemoveClient(client);
    }
}

 

ytw_developer