.NET Socket.Receive () не получает большие потоки данных от Java SocketServer - PullRequest
4 голосов
/ 28 октября 2010

Java Socket Server


У меня есть процесс Java, который создает прослушиватель на сокете TCP с использованием java.io.ServerSocket что-то вроде этого (упрощенно):

ServerSocket server = new ServerSocket(4444,20);
server.accept();

Процесс Java запускает рабочий поток при получении запроса, а затем рабочий отправляет строку JSON, используя java.io.PrintWriter и java.net.Socket:

PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
out.println("JSON STRING");
out.flush();
out.close();
clientSocket.close();

Я упростилкод Java, но по сути это все, что он делает.


.NET Socket Client


Далее у меня есть приложение .NET, которое связывается с компьютером, на котором размещен этот процесс Java:

//Create Connection
Socket clientSocket = new Socket(AddressFamily.InterNetwork, 
                                 StreamType.Stream, ProtocolType.Tcp);
mySocket.Connect("192.168.1.102", 4444);

//Initialize Byte Buffer Larger than Expected JSON String and Read Bytes
byte[] receivedData = new byte[524288];
int numberOfBytes = clientSocket.Receive(receivedData, SocketFlags.None);
clientSocket.Close();

//Populate a new byte array of the exact size received with the received data
byte[] formatedBytes = new byte[numberOfBytes];
for (int i=0; i< numberOfBytes; i++)
{
    formatedBytes[i] = receivedData[i];
}

//Convert Byte Array to String & Output Results
Response.ClearContent();
Response.ContentType("text/plain");
Response.Write(new System.Text.ASCIIEncoding().GetString(receivedData));

Моя проблема заключается в том, что по какой-либо причине эта реализация не работает, когда я пытаюсь отправить несколько больших строк JSON через Socket Stream.С небольшими размерами данных (менее 2 КБ) я успешно протестировал эту реализацию с более чем 100 Клиентами, подключающимися и получающими данные без каких-либо проблем, однако попытка увеличить размер строки JSON до примерно 256 КБ приводит к усечению результатов приложением .NET.Увеличение размера массива байтового буфера также не помогает - кажется, что приложение .NET разрывает соединение до того, как передаются все данные, или приложение Java не отправляет всю строку с помощью PrintWriter.

Буду очень признателен за любую информацию по этому вопросу - я буду публиковать любые обновления, если я сам что-то сделаю.


Вот решение, к которому я пришел - сервер работает отлично!Еще раз спасибо!


    byte[] receivedData = new byte[512000]; // 4 Meg Buffer

    Socket mySocket = new Socket(AddressFamily.InterNetwork, 
                               SocketType.Stream, ProtocolType.Tcp);
    mySocket.Connect("172.26.190.205", 4444);
    mySocket.ReceiveBufferSize = 8192;

    int numberOfBytesRead = 0;
    int totalNumberOfBytes = 0;
    do
    {
        numberOfBytesRead = mySocket.Receive(receivedData,totalNumberOfBytes ,
                            mySocket.ReceiveBufferSize,SocketFlags.None);
        totalNumberOfBytes += numberOfBytesRead;
    } 
    while (numberOfBytesRead > 0);
    mySocket.Close();

    byte[] formatedBytes = new byte[totalNumberOfBytes ];
    for (int i = 0; i < totalNumberOfBytes ; i++)
    {
        formatedBytes[i] = receivedData[i];
    }
    Response.ClearContent();
    Response.ContentType = "text/plain";
    Response.Write(new System.Text.ASCIIEncoding().GetString(formatedBytes));

Ответы [ 2 ]

3 голосов
/ 28 октября 2010

Хотя TCP является концепцией потока , базовый IP отправляет и получает пакетов . Для приложения это означает, что вы всегда читаете из сокета в цикле , потому что одна «запись» отправителем может привести к многократным «чтениям» получателем, и наоборот. вокруг.

Это сводится к тому, что реализация стека TCP / IP зависит от способа разделения данных, которые вы отправляете, на пакеты. Принимающая сторона, опять же сетевой стек, не знает, сколько байтов ожидать. Он просто берет то, что получил, и запускает процесс, который ожидает в этом сокете, если он есть, или буферизует байты в противном случае.

Ваш случай прост - просто продолжайте чтение из сокета до тех пор, пока не увидите EOF, то есть считанные ноль байтов. Но в целом вам необходим протокол уровня приложения, который либо определяет длину сообщения, устанавливает правила для границ сообщения или встраивает информацию о явной длине в сами сообщения.

0 голосов
/ 28 октября 2010

// Инициализация байтового буфера больше, чем Ожидаемые строки JSON и прочитанные байты byte [] receiveData = new байты [524288]; int numberOfBytes = clientSocket.Receive (receivedData, SocketFlags.None); clientSocket.Close ();

Хорошо, это читает все байты, которые поступают в буфер. Затем закрывает поток. Ups.

Прочтите документацию - для метода Receive. Вы должны повторно звонить, пока не получите больше данных. Он будет блокироваться до получения НЕКОТОРЫХ данных, а затем вернет это. Он НЕ будет ждать, пока ВСЕ данные поступят.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...