Сокетная связь между C и java

У меня есть клиент и сервер, работающие на C. Моя задача - представить java-программу, в которой я создаю сервер для клиента C и клиент для сервера C. Мне удалось правильно настроить соединения. Однако проблема заключается в передаче данных между обеими программами C. Ниже приведено то, что я написал в своей java-программе:

while(true){
while((userInput1=br1.readLine())!=null||(userInput2=br2.readLine())!=null){
   if(userInput1=!null){
      bw1.write(userInput1);
      bw1.flush();
   }
   if(userInput2=!null){
      bw2.write(userInput2);
      bw2.flush();
   }
}    

При отладке вышеизложенного видно, что выполнение застряло на втором операторе while, что означает, что входной поток вечно ожидает ввода для клиента C. Я использую BufferedReader и BufferedWriter для потоков. Клиент C и сервер используют функции send и recv для связи. Пожалуйста, помогите с любыми входными данными, чтобы программа Java помогла обеим программам C общаться друг с другом, как они обходятся без этого.


person user_abh    schedule 19.10.2011    source источник
comment
Я мало что знаю о сетях Java, но мне кажется, что сокеты, используемые для чтения, блокируются. Вам нужно использовать неблокирующие сокеты.   -  person Some programmer dude    schedule 19.10.2011
comment
У вас есть два соединения сокета, вы хотите, чтобы второй блок соединения был всякий раз, когда первое соединение не отправляет данные?? Есть ли причина, по которой вы не используете потоки, чтобы соединения сокетов можно было читать независимо. Если есть зависимость между двумя соединениями, не могли бы вы сказать, что это такое?   -  person Peter Lawrey    schedule 19.10.2011


Ответы (3)


Вы правильно рассмотрели эффект «короткого замыкания» или оператора Java?

С || если первое предложение истинно, второе никогда не оценивается.

   while(
        (userInput1=br1.readLine())!=null ||
        (userInput2=br2.readLine())!=null) {

Итак, вы успешно прочитали

 userInput1=br1.readLine())!=null

и сразу же введите свою обработку, затем вернитесь к while и снова прочитайте следующую строку в userInput1. Следовательно, userInput2 никогда не получит значение.

Вам нужна отдельная логика, например

    read first line
    read second line 

Но что именно вы должны делать, когда читаете строку 2, а данные не готовы? Попробуйте еще раз? Является ли строка, которую вы читаете следующей, ожидаемой строкой 2 или новой строкой 1? Это довольно сложно сделать правильно.

Я бы предпочел не полагаться на две отдельные строки чтения в своем протоколе.

person djna    schedule 19.10.2011
comment
Я использовал || оператора, имея в виду, что только в один момент времени либо клиент, либо сервер будут готовы дать ввод, в то время как другой ждет этого ввода или будет участвовать в некоторых собственных операциях. поэтому каждый раз, когда запускается цикл while, любое из условий должно выполняться (ввод будет дан на стороне клиента или сервера) и, соответственно, этот ввод должен быть записан в соответствующий выходной поток. - person user_abh; 19.10.2011
comment
и позвольте мне также обратить ваше внимание на то, что, хотя выполнение застревает на втором операторе while, если я завершаю клиентскую программу C, уже заданный ввод теперь записывается в поток вывода сервера, и сервер начинает отвечать на этот ввод т. е. только когда клиентская программа завершается, она понимает, что достигла конца буфера. Любые входные данные, пожалуйста? - person user_abh; 19.10.2011
comment
Итак, у вас есть код, смешивающий клиентскую и серверную части? Извините не понял этого. На мой вкус, это не чистый дизайн. - person djna; 19.10.2011
comment
Поэтому вы рекомендуете написать 2 отдельные Java-программы, одну для работы в качестве клиента для фактического C-сервера, а другую — в качестве сервера для фактического C-клиента. А затем установить соединение между этим клиент-серверным дуэтом. Прошу прощения, если я покажусь здесь чрезмерно злоупотребляющим людьми. Я только в процессе обучения.. Пожалуйста, посоветуйте.. - person user_abh; 19.10.2011
comment
Да, отдельные клиентские и серверные программы или, по крайней мере, отдельные методы работы с клиентской и серверной частями. Я утверждаю, что ваш код будет легче понять, разделив задачи. - person djna; 21.10.2011

while((userInput1=br1.readLine())!=null||(userInput2=br2.readLine())!=null){

Это условие означает, что вы прочитаете br1 до EOS, прежде чем прочтете что-либо из br2. Это то, что вы действительно намеревались?

И наоборот, если вы застряли на br2.readLine(), это означает две вещи: (а) br1 находится в EOS, и (б) одноранговый узел, связанный с br2, ничего не отправлял или, по крайней мере, не отправлял строку, заканчивающуюся новой строкой.

Возможно, вы страдаете от распространенного заблуждения, что readLine() возвращает null, когда нет данных, готовых для чтения?

Также вы читаете строки, заканчивающиеся символами новой строки, которые удаляются вызовом readLine(), а затем записываете их без каких-либо символов новой строки, что вряд ли может быть правильным.

Мне кажется, что то, что вы на самом деле пишете, является прокси, и в этом случае вам нужно два потока на сокет, один для чтения из A и для записи в B, а другой для чтения из B и для записи в A. И если это прокси, вы следует использовать InputStreams и OutputStreams, а не Readers и Writers, поскольку у вас, вероятно, нет причин проверять данные, и поэтому вам не следует проводить их через процессы преобразования byte-> char и char-> byte, подразумеваемые использованием Readers и Writers. Есть и другие тонкости при написании прокси, но я подожду вашего подтверждения, прежде чем объяснять их.

person user207421    schedule 19.10.2011
comment
У меня есть 2 потока, которые сейчас отлично работают. Я использовал br1.ready() и br2.ready(), чтобы узнать, есть ли какие-либо данные в потоках. А также использовал технику добавления символа четности в исходные программы-коммуникаторы для отправки данных через мой прокси. Теперь я читаю данные, пока не столкнусь с этой четностью и не отправлю ее на другую сторону взаимодействующей части. Кажется, это работает нормально. И да, я все еще продолжаю использовать InputStreamReader и OutputStreamWriter. Пожалуйста, просветите меня, если есть лучший способ справиться с этим. Спасибо. - person user_abh; 25.10.2011
comment
@abhiram Не используйте ready(). У вас есть две темы. Блокировать. Что еще потоки собираются делать в любом случае? И вы должны использовать Readers и Writers только в том случае, если вы знаете, что данные являются только символьными данными. Если есть какая-либо настоящая будущая или отдаленная возможность того, что это будет бинарным, используйте потоки: другими словами, используйте потоки. Я не знаю, зачем вам нужна эта штука с четностью, когда вы только выступаете посредником между клиентом и сервером, то есть вы являетесь прокси. Просто скопируйте байты в обоих направлениях. - person user207421; 25.10.2011

причина, по которой я использую символ четности, заключается в интерпретации конца потока. В противном случае использование только read() приводит к остановке программы для ввода навсегда (даже после того, как фактическая отправка всех своих данных). Я использую ready() следующим образом:

//The proxy client
while(true){
    if(br1.ready()){
        while((temp1=br1.read())!=(int)par)
            userInput1=userInput1+(char)temp1;
        System.out.println("Input to Actual Server: " + userInput1);
        bw1.write(userInput1);
        bw1.flush();
        System.out.flush();
        userInput1="";
        temp1=0;
        }
        if(br2.ready()){
            while((temp2=br2.read())!=(int)par)
                userInput2=userInput2+(char)temp2;
            System.out.println("Response from Actual Server: " + userInput2);
            userInput2=userInput2+par;
            bw2.write(userInput2);
            bw2.flush();
            System.out.flush();
            userInput2="";
            temp2=0;
        }
}

//The proxy server
while(true){
     if(br1.ready()){
         while((temp1=br1.read())!=(int)par)
                         userInput1=userInput1+(char)temp1;
         System.out.println("Input from Actual Client: " + userInput1);
         userInput1=userInput1+par;
         bw1.write(userInput1);
         bw1.flush();
         System.out.flush();
         userInput1="";
         temp1=0;
     }
     if(br2.ready()){
         while((temp2=br2.read())!=(int)par)
                userInput2=userInput2+(char)temp2;
         System.out.println("Response to Actual Client: " + userInput2);
         bw2.write(userInput2);
         bw2.flush();
         System.out.flush();
         userInput2="";
         temp2=0;
     }
}

Пожалуйста, предложите, если есть какие-либо проблемы с использованием ready().

person user_abh    schedule 27.10.2011
comment
Хорошо, я внес несколько изменений в вышеизложенное. Используется метод available() в BuffereInputStream, чтобы узнать, есть ли еще данные в потоке, и, таким образом, нет необходимости использовать символ четности. Больше нет необходимости использовать ready(). - person user_abh; 27.10.2011