Зависание при отправке нескольких байтов [] с клиента C # на сервер Java с использованием одного и того же сетевого потока и сокета - PullRequest
0 голосов
/ 26 февраля 2012

Я написал загрузчик файлов, предназначенный для отправки файла программного кода с клиента C # на сервер Java. Сервер требует, чтобы действительное имя пользователя и пароль были отправлены до принятия загрузки файла.

Независимо как защита (имя пользователя и пароль), так и загрузчик файлов работают правильно. Однако, когда я пытаюсь объединить два, код зависает на клиенте C # после получения «истинного» логического ответа от сервера (с указанием правильного имени пользователя и пароля). Соответствующий код от клиента и сервера прилагается.

C # Клиент

public static string sendValidatedFile(string username, string password, string path) {

        string inputString = "NotSent";

        try {

            TcpClient client = new TcpClient("127.0.0.1", 42000);

            StreamReader input = new StreamReader(stream);

            Stream securityStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(username + "_" + password + "_\n"));

            byte[] bufferA = new byte[securityStream.Length];
            securityStream.Read(bufferA, 0, bufferA.Length);

            stream.Write(bufferA, 0, bufferA.Length);
            stream.Flush();

            inputString = input.ReadToEnd();
            bool result = bool.Parse(inputString);

            if (result) {

                print("Login Accepted");

                Stream fileStream = File.OpenRead(path);

                byte[] buffer = new byte[fileStream.Length];
                fileStream.Read(buffer, 0, buffer.Length);

                // This is where the code seems to lock up
                stream.Write(buffer, 0, buffer.Length);
                stream.Flush();

                inputString = input.ReadToEnd();

            }

            else {

                inputString = "Invalid Username or Password";

            }

            input.Close();
            stream.Close();
            client.Close();

        }

        catch (SocketException e) {

            print("Error" + e);

        }

        catch (IOException e) {

            print("Error" + e);

        }

        return inputString;

    }

Java Server

public void run() {

try {

  // Get username and password
    byte[] byteArrayJAR = new byte[filesize];
    byte[] byteArraySecurity = new byte[filesize];
    InputStream input = socket.getInputStream();
    PrintWriter output = new PrintWriter(socket.getOutputStream());

    int bytesSecurity = input.read(byteArraySecurity, 0, byteArraySecurity.length);
    int currentByte1 = bytesSecurity;

    if (input.available() > 0) {

        do {

            bytesSecurity = input.read(
                    byteArraySecurity,
                    currentByte1,
                    (byteArraySecurity.length - currentByte1));

            if (bytesSecurity >= 0) {

                currentByte1 += bytesSecurity;

            }
        }

        while (bytesSecurity > -1);
    }

    String securityString = new String(byteArraySecurity).trim();
    String[] authenticationString = securityString.split("_");
    String username = authenticationString[0];
    String password = authenticationString[1];

  // Validate the username and password with a stored database
    if (security.validateUser(username, password)) {

       // Inforn the client their username and password were accepted
        output.println(true);
        output.flush();

      // Get the program code file
        int bytesRead = input.read(byteArrayJAR, 0, byteArrayJAR.length);
        int currentByte = bytesRead;

       if (input.available() > 0) {

                do {

                   bytesRead = input.read(
                     byteArrayJAR,
                            currentByte,
                            (byteArrayJAR.length - currentByte));

                if (bytesRead >= 0) {

                        currentByte += bytesRead;

                    }
             }

                 while (bytesRead > -1);

     }

      // Inform the client that the code was received
        output.println("Success");
        output.flush();

    }

    else {

      // Inform the client their username or password was incorrect
        output.println(false);
        output.flush();

    }

  // Disconnect from client
    output.flush();
    output.close();
    input.close();
    socket.close();

}

catch (IOException e) {

    e.printStackTrace();

}

}

Может кто-нибудь увидеть что-то не так с вышеприведенным, что может привести к зависанию моего кода? Определенно должны быть данные для клиента C # для передачи в обоих случаях. Есть ли причина, по которой два байтовых массива не могут быть отправлены из одного сетевого потока в C #?

Буду признателен за любую помощь, которую кто-нибудь может предложить, чтобы приведенный выше код работал без зависаний.

С уважением,

Midavi.

1 Ответ

0 голосов
/ 26 февраля 2012

Вы используете input.ReadToEnd () дважды. Поток имеет только один конец; Я подозреваю, что первое из них неуместно и должно быть заменено более прямым чтением - или, в лучшем случае, ReadLine ().

Если разговор здесь зависит от нескольких сообщений между клиентом и сервером, вы также можете проверить, включен ли nagle, поскольку может случиться так, что одно из сообщений все еще находится в буфере и еще не было отправлено (Flush () ничего не делает в сетевом потоке) - возможно, вам придется установить NoDelay (или эквивалент) для сокета. Поведение по умолчанию - буферизовать небольшие сообщения, чтобы предотвратить переполнение сети множеством крошечных пакетов.

...