Последовательное соединение RXTX - проблема с блокировкой чтения ()
Я пытаюсь использовать библиотеку RXTX для блокировки последовательной связи в Windows (XP и 7). Я проверил соединение с Hyperterminal в обоих концах, и оно работает безупречно.
Я установил соединение с помощью следующего кода: (обработка исключений и защитные проверки опущены для ясности)
private InputStream inStream;
private OutputStream outStream;
private BufferedReader inReader;
private PrintWriter outWriter;
private SerialPort serialPort;
private final String serialPortName;
public StreamComSerial(String serialPortName) {
this.serialPortName = serialPortName;
CommPortIdentifier portIdentifier;
portIdentifier = CommPortIdentifier.getPortIdentifier(serialPortName);
CommPort commPort = null;
commPort = portIdentifier.open(this.getClass().getName(),500);
serialPort = (SerialPort) commPort; serialPort.setSerialPortParams(4800,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
inStream = serialPort.getInputStream();
outStream = serialPort.getOutputStream();
inReader = new BufferedReader(new InputStreamReader(inStream, Settings.getCharset()));
outWriter = new PrintWriter(new OutputStreamWriter(outStream, Settings.getCharset()));
Когда я использую
outWriter.println("test message");
flush();
сообщение получено нормально на другом конце, но звонит
inReader.readLine()
немедленно возвращает "java.io.IOException: основной поток ввода возвратил ноль байтов".
Затем я решил попробовать реализовать собственную логику чтения блокировки и написал это:
public String readLine() throws IOException {
String line = new String();
byte[] nextByte = {-1};
while (true) {
nextByte[0] = (byte)inStream.read();
logger.debug("int read: " + nextByte[0]);
if (nextByte[0] == (byte)-1) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
continue;
}
logger.debug("byte read: " + nextByte[0]);
line = line + new String(nextByte);
if (nextByte[0] == (byte)13) { // 13 is carriage return in ASCII
return line;
}
}
}
Но этот код идет в бесконечном цикле и "nextByte[0] = (byte)inStream.read();" присваивает -1 независимо от того, что отправляется через последовательное соединение. Кроме того, другой конец довольно сильно заикается и позволяет мне посылать персонажа каждые 1-3 секунды. и зависает долго, если я пытаюсь отправить много символов в короткий пакет.
Любая помощь очень ценится.
* edit - использование inStream.read(nextByte) вместо "nextByte[0] = (byte)inStream.read();" не записывает в переменную nextByte, что бы я ни отправлял через последовательное соединение.
* edit2 - так как мой код безупречно работает с библиотекой SUN javax.comm и win32com.dll, которые я получил от друга, я прекратил попытки заставить его работать с RXTX. Меня не интересует разблокировка связи, которая, кажется, является единственным способом, которым другие люди могут заставить работать RXTX.
4 ответа
Используйте RXTX-2.2pre2, в предыдущих версиях была ошибка, из-за которой блокировка ввода / вывода работала некорректно.
И не забудьте установить порт в режим блокировки:
serialPort.disableReceiveTimeout();
serialPort.enableReceiveThreshold(1);
Я думаю, что код, который вы написали в своей собственной реализации readLine, содержит ошибки. nextByte[0] никогда не восстанавливается до -1 после чтения первого символа. Вы должны попытаться использовать значение, возвращаемое inStream.read(nextByte), чтобы указать количество байтов, прочитанных из потока, вместо значения вашего байтового массива.
В любом случае, я думаю, вам следует использовать метод чтения событий, основанный на событиях, с помощью SerialPortEventListener:
serialPort.addEventListener(new SerialPortEventListener() {
public void serialEvent(SerialPortEvent evt) {
switch (evt.getEventType()) {
case SerialPortEvent.DATA_AVAILABLE:
dataReceived();
break;
default:
break;
}
}
});
serialPort.notifyOnDataAvailable(true);
Это может быть не блокировка, но когда поток пуст, просто перехватите IOE и продолжайте чтение из него. Это то, что я делаю с RXTX-2.1-7, и он отлично работает, я использую его для чтения и записи в arduino:
public static class SerialReader implements Runnable {
InputStream in;
public SerialReader(InputStream in) {
this.in = in;
}
public void run() {
Boolean keepRunning = true;
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while (keepRunning) {
try {
while ((line = br.readLine()) != null) {
//DO YOUR STUFF HERE
}
} catch (IOException e) {
try {
//ignore it, the stream is temporarily empty,RXTX's just whining
Thread.sleep(200);
} catch (InterruptedException ex) {
// something interrupted our sleep, exit ...
keepRunning = false;
}
}
}
}
}
Я решил так
try
{
if(input.ready()==true)
{
String inputLine=input.readLine();
System.out.println(inputLine);
}
} catch (Exception e)