解决 如果有人有兴趣,我可以用正确的数据编辑这篇文章。只需发表评论。
作为我的任务,我必须使用非阻塞通道和选择器创建一个简单的服务器和客户端。 基本上它应该回显客户端写入的消息或添加两个数字(也由客户端提供)。
我的问题是我在消息即将被服务器回应时出现错误。 我已经检查过msg是否有writeResponse方法,而且确实如此。这就是问题出现的地方。
提前谢谢大家!
我得到的错误:
java.io.IOException: An existing connection was forcibly closed by the remote host
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:218)
at sun.nio.ch.IOUtil.read(IOUtil.java:191)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:359)
at SimpleServer.serviceRequest(SimpleServer.java:89)
at SimpleServer.serviceConnections(SimpleServer.java:61)
at SimpleServer.<init>(SimpleServer.java:35)
at SimpleServer.main(SimpleServer.java:141)
服务器:
public class SimpleServer {
private ServerSocketChannel ssc = null; //for multiplexing
private Selector selector = null; //monitors channels
private static Charset charset = Charset.defaultCharset();//encoding
private static final int BSIZE = 1024;//buffer size
private ByteBuffer bbuf = ByteBuffer.allocate(BSIZE);
private StringBuffer reqString = new StringBuffer();
public SimpleServer(String host, int port) {
try {
ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
ssc.socket().bind(new InetSocketAddress(host, port));
selector = Selector.open(); //selector initiation
ssc.register(selector, SelectionKey.OP_ACCEPT); //registering communication channel
} catch(Exception exc) {
exc.printStackTrace();
System.out.println(1);
}
System.out.println("Server started and is ready for requests");
serviceConnections();
}//constructor
private void serviceConnections() {
boolean serverIsRunning = true;
while(serverIsRunning) {
try {
selector.select();//waits for answer from selector
Set<SelectionKey> keys = selector.selectedKeys(); //set of keys
Iterator<SelectionKey> iter = keys.iterator(); //iterration throught set of keys
while(iter.hasNext()) {
SelectionKey key = (SelectionKey) iter.next(); //obtain key
iter.remove(); //remove, because we'd get it again
if(key.isAcceptable()) {
SocketChannel cc = ssc.accept();//obtaining channel for communication
cc.configureBlocking(false);
cc.register(selector, SelectionKey.OP_READ); //registering selector for monitoring
continue;
}
if(key.isReadable()) { //channel with readable data
SocketChannel cc = (SocketChannel) key.channel();
serviceRequest(cc);
continue;
}
}//while loop
} catch(Exception exc) {
exc.printStackTrace();
continue;
}
}//outer while loop
}//serviceCconnection method
private void serviceRequest(SocketChannel sc) {
if(!sc.isOpen()) return;
reqString.setLength(0);
bbuf.clear();
try {
readLoop:
while (true) {
int n = sc.read(bbuf);
if(n > 0) {
bbuf.flip();//set limit, return to beginning
CharBuffer cbuf = charset.decode(bbuf);
while(cbuf.hasRemaining()) {
char c = cbuf.get();
if (c == '\r' || c == '\n') break readLoop;
reqString.append(c);
}
}
}//while loop
String[] req = reqString.toString().split(" ");
String cmd = req[0];
if (cmd.equals("bye")) {
sc.close();
sc.socket().close();
}
else if(cmd.equals("echo"))
writeResp(sc, reqString.toString());
else if(cmd.equals("add"))
writeResp(sc, Integer.parseInt(req[1]),Integer.parseInt( req[2]));
} catch (Exception exc) {
exc.printStackTrace();
try { sc.close();
sc.socket().close();
} catch (Exception e) {}
}
}//serviceRequest
//overloaded methods
public void writeResp(SocketChannel sc, String msg) throws IOException {
System.out.println(msg);
ByteBuffer cbuf = charset.encode(CharBuffer.wrap(msg));
cbuf = ByteBuffer.allocate(1024);
cbuf.put(msg.getBytes());
cbuf.rewind();
sc.write(cbuf);
}//writeResp method
public void writeResp(SocketChannel sc, int i, int j) throws IOException, NumberFormatException {
int ans = i + j;
String resp = Integer.toString(ans);
ByteBuffer cbuf = charset.encode(CharBuffer.wrap(resp));
sc.write(cbuf);
}//write Resp method
public static void main(String[] args) {
try {
String host = "localhost";
int port = 9998;
new SimpleServer(host, port);
} catch(Exception exc) {
exc.printStackTrace();
System.out.println(1);
}
}//main
}//class
我的客户:
public class SimpleClient {
private SocketChannel sc;
private static Charset charset;
private StringBuffer reqString = new StringBuffer();
private ByteBuffer bb;
String msg;
public SimpleClient(String host, int port) throws IOException, InterruptedException {
try {
sc = SocketChannel.open();
sc.configureBlocking(false);
sc.connect(new InetSocketAddress(host, port));
System.out.println("Connecting to the server...");
while(!sc.finishConnect()) {
System.out.println("Connection is being established...");
}
} catch (IOException exc) {
System.out.println("IO exception");
System.exit(1);
}
System.out.println("Connection Established!");
makeRequest("echo Test input stream\n");
Thread.sleep(500);
readRequest();
}//constructor
private void makeRequest(String req) throws IOException {
System.out.println("Request: " + req);
bb = ByteBuffer.allocate(1024);
bb.put(req.getBytes());
bb.rewind();
sc.write(bb);
}//makeRequest method
public void readRequest() throws IOException, InterruptedException {
reqString.setLength(0);
bb.clear();
try {
readLoop:
while (true) {
bb.clear();
int readBytes = sc.read(bb);
if(readBytes == 0){
System.out.println("waiting for data");
continue;
}
else if(readBytes == -1) {
System.out.println("Server not responding");
break;
}
else {
bb.flip();
CharBuffer cbuf = charset.decode(bb);
while(cbuf.hasRemaining()) {
char c = cbuf.get();
if (c == '\r' || c == '\n') break readLoop;
reqString.append(c);
}
}
}//while loop
System.out.println(reqString.toString());
} catch( Exception exc) {//while loop
exc.printStackTrace();
}
}//readRequest method
public static void main(String[] args) {
try {
new SimpleClient("localhost", 9998);
}catch (IOException exc) {
exc.printStackTrace();
}catch(InterruptedException exc) {
exc.printStackTrace();
}
}//main method
}//class
答案 0 :(得分:0)
如果read()返回-1,则表示“服务器没有响应”。这意味着对等方已关闭连接,您也应该这样做。相反,您根本没有关闭它,因此操作系统会重置,因此您的服务器会获得此异常。