java套接字InputStream在客户端和服务器上都挂起/阻塞
大家好 我最近正在开发一个小程序,旨在远程关闭浏览器。 基本程序如下:java套接字InputStream在客户端和服务器上都挂起/阻塞,java,sockets,Java,Sockets,大家好 我最近正在开发一个小程序,旨在远程关闭浏览器。 基本程序如下: 服务器端: 创建一个SocketServer以侦听某个特定端口 接受连接并创建相应的套接字对象 从已创建的套接字读取InputStream(在此端口上被阻止 操作) 客户端: 创建套接字对象以建立与服务器的连接 通过写入来发送关闭服务器端浏览器的命令 要输出流的字节数 在的InputStream上使用Read()读取来自服务器的反馈 套接字(在此操作中被阻止) 下面的代码: Server.java package so
服务器端:
客户端:
下面的代码:
Server.java
package socket;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Enumeration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server {
private static ExecutorService es = Executors.newFixedThreadPool(5);
public static void main(String[] args) throws IOException {
InetAddress targetAddress = null;
NetworkInterface ni = NetworkInterface.getByName("eth2");
System.out.println(ni);
Enumeration<InetAddress> inetAddresses = ni.getInetAddresses();
while(inetAddresses.hasMoreElements()) {
InetAddress inetAddress = inetAddresses.nextElement();
if(inetAddress.toString().startsWith("/10")) {
targetAddress = inetAddress;
break;
}
}
ServerSocket sSocket = new ServerSocket(11111, 0, targetAddress);
while(true) {
System.out.println("Server is running...");
Socket client = sSocket.accept();
System.out.println("Client at: " + client.getRemoteSocketAddress());
es.execute(new ClientRequest(client));
}
}
}
package socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientRequest implements Runnable {
private Socket client;
public ClientRequest(Socket client) {
this.client = client;
}
@Override
public void run() {
try {
System.out.println("Handled by: " + Thread.currentThread().getName());
// get input/output streams for client socket
InputStream cis = client.getInputStream();
OutputStream cos = client.getOutputStream();
// buffer size : 1024 ?
byte[] buffer = new byte[1024];
int recvSize;
int totalRecvSize = 0;
while(-1 != (recvSize = cis.read(buffer, totalRecvSize, 1024 - totalRecvSize))) {
totalRecvSize += recvSize;
}
String command = new String(buffer, "utf-8");
System.out.println("Command from client: " + command);
String commandNative = CommandMap.getNativeCommand(command.trim());
if(null != commandNative) {
Process np = Runtime.getRuntime().exec(commandNative);
InputStream is = np.getInputStream();
byte[] bufferProcess = new byte[1024];
int bytesRead;
int totalBytesRead = 0;
while(-1 != (bytesRead = is.read(bufferProcess, totalBytesRead, 1024 - totalBytesRead))) {
totalBytesRead += bytesRead;
}
// give feed back of process output
cos.write(bufferProcess);
// close process input stream
is.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(null != client) {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
public class Client {
private static final int BUF_SIZE = 1024;
// feedback message size will not exceed 1024 bytes
private static final byte[] BUFFER = new byte[BUF_SIZE];
public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {
Socket socket = new Socket("10.117.37.176", 11111);
System.out.println("Connected to Server...");
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
String command = "kill ie";
byte[] commandBytes = command.getBytes(Charset.forName("utf-8"));
System.out.println("Send: " + command);
os.write(commandBytes);
System.out.println("After send: " + command);
int totalRecv = 0;
int recvSize;
while(-1 != (recvSize = is.read(BUFFER, totalRecv, BUF_SIZE - totalRecv))) {
totalRecv += recvSize;
}
String feedback = new String(BUFFER, "utf-8");
System.out.println("Feedback: " + feedback);
socket.close();
}
}
最后,Client.java
package socket;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Enumeration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server {
private static ExecutorService es = Executors.newFixedThreadPool(5);
public static void main(String[] args) throws IOException {
InetAddress targetAddress = null;
NetworkInterface ni = NetworkInterface.getByName("eth2");
System.out.println(ni);
Enumeration<InetAddress> inetAddresses = ni.getInetAddresses();
while(inetAddresses.hasMoreElements()) {
InetAddress inetAddress = inetAddresses.nextElement();
if(inetAddress.toString().startsWith("/10")) {
targetAddress = inetAddress;
break;
}
}
ServerSocket sSocket = new ServerSocket(11111, 0, targetAddress);
while(true) {
System.out.println("Server is running...");
Socket client = sSocket.accept();
System.out.println("Client at: " + client.getRemoteSocketAddress());
es.execute(new ClientRequest(client));
}
}
}
package socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientRequest implements Runnable {
private Socket client;
public ClientRequest(Socket client) {
this.client = client;
}
@Override
public void run() {
try {
System.out.println("Handled by: " + Thread.currentThread().getName());
// get input/output streams for client socket
InputStream cis = client.getInputStream();
OutputStream cos = client.getOutputStream();
// buffer size : 1024 ?
byte[] buffer = new byte[1024];
int recvSize;
int totalRecvSize = 0;
while(-1 != (recvSize = cis.read(buffer, totalRecvSize, 1024 - totalRecvSize))) {
totalRecvSize += recvSize;
}
String command = new String(buffer, "utf-8");
System.out.println("Command from client: " + command);
String commandNative = CommandMap.getNativeCommand(command.trim());
if(null != commandNative) {
Process np = Runtime.getRuntime().exec(commandNative);
InputStream is = np.getInputStream();
byte[] bufferProcess = new byte[1024];
int bytesRead;
int totalBytesRead = 0;
while(-1 != (bytesRead = is.read(bufferProcess, totalBytesRead, 1024 - totalBytesRead))) {
totalBytesRead += bytesRead;
}
// give feed back of process output
cos.write(bufferProcess);
// close process input stream
is.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(null != client) {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
public class Client {
private static final int BUF_SIZE = 1024;
// feedback message size will not exceed 1024 bytes
private static final byte[] BUFFER = new byte[BUF_SIZE];
public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {
Socket socket = new Socket("10.117.37.176", 11111);
System.out.println("Connected to Server...");
OutputStream os = socket.getOutputStream();
InputStream is = socket.getInputStream();
String command = "kill ie";
byte[] commandBytes = command.getBytes(Charset.forName("utf-8"));
System.out.println("Send: " + command);
os.write(commandBytes);
System.out.println("After send: " + command);
int totalRecv = 0;
int recvSize;
while(-1 != (recvSize = is.read(BUFFER, totalRecv, BUF_SIZE - totalRecv))) {
totalRecv += recvSize;
}
String feedback = new String(BUFFER, "utf-8");
System.out.println("Feedback: " + feedback);
socket.close();
}
}
要重申这些问题:- 服务器端无法通过调用read(buffer, 套接字的InputStream对象上的偏移量,len)。它会阻塞
- 客户端无法通过调用read(buffer, 其套接字的InputStream对象上的偏移量,len)。它会阻塞
- 但当我在中注释掉反馈读取操作时 java,服务器和客户端都能正常工作
我想知道这些代码中隐藏的原因是什么?
希望有人能帮助我,谢谢
您的套接字读取代码正在读取,直到EOF。在关闭插座之前,您不会收到EOF。因此,您的代码永远不会继续 如果只想在套接字连接上发送一个命令,则在写入命令后关闭OutputStream(使用
socket.shutdownOutput()
)
如果您想在一个套接字连接上发送多个命令,那么您需要找到一种方法来界定每个命令()。您正在读取两端的EOS,这是一个糟糕的选择,因为您无法“发送”EOS而不失去在同一连接上发送更多数据的能力。您需要重新设计应用程序协议,以便可以一次读取命令,而无需关闭连接即可完成。例如,发送行、字长前缀、自描述协议(如XML或Java对象序列化)或任何可以通过DataInputStream读取而不依赖EOFEException的内容。感谢您的精彩回答!但是仍然存在一个问题,客户端希望获得一些反馈,在我的例子中,反馈应该是本机命令的输出(旨在关闭浏览器)。如果我添加os.close(),当我在InputStream上调用read()方法时,将抛出一个SocketException,并显示消息“socket closed”,我如何处理这个问题?非常感谢。@destiny1020-你试过我的建议了吗?关闭outputstream独立于关闭inputstream。是的,我已经尝试了您的建议,我在Client.java中的os.write()之后添加了一行os.close()。但是当我尝试调用in.read()方法时有一个例外:socketclosed,可能close底层OutputStream会间接关闭Socket连接?我对此感到困惑。谢谢你的回复!我用自己的close()方法关闭输出流,实际上应该调用socket.shutdownOutput(),我已经弄明白了。谢谢你的建议,太棒了@destiny1020-啊,很抱歉,我会更新我的答案。我认为直接关闭outputstream是实现这一点的方法。我已经有一段时间没有使用套接字了。谢谢你的建议,我的应用程序确实存在一些设计问题。非常感谢。