gpt4 book ai didi

java socket InputStream 在客户端和服务器上挂起/阻塞

转载 作者:搜寻专家 更新时间:2023-11-01 01:08:28 26 4
gpt4 key购买 nike

我最近在开发一个旨在远程关闭浏览器的小程序。基本流程如下:

服务器端:

  1. 创建一个 SocketServer 来监听某个端口。
  2. 接受连接并创建相应的套接字对象
  3. 从创建的套接字中读取 InputStream(在此操作时被阻塞)

客户端:

  1. 创建一个套接字对象以与服务器建立连接。
  2. 通过向 OutputStream 写入字节来发送关闭服务器端浏览器的命令。
  3. 在套接字的 InputStream 上使用 read() 读取来自服务器的反馈(在此操作时被阻塞)

代码如下:

服务器.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));
}

}
}

ClientRequest.java

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();
}
}
}
}

最后,Client.java

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();
}
}

重申问题:

  • 服务器端无法通过对套接字的 InputStream 对象调用 read(buffer, offset, len) 来读取命令。它会阻止。
  • 客户端无法通过对其套接字的 InputStream 对象调用 read(buffer, offset, len) 来读取反馈。它会阻止。
  • 但是当我注释掉 Client.java 中的反馈读取操作时,server 和 slient 都可以正常工作。

我想知道这段代码中隐藏的原因是什么?

最佳答案

您的套接字读取代码一直读取到 EOF。在关闭套接字之前,您不会收到 EOF。因此,您的代码永远不会继续。

如果您只想在套接字连接上发送单个命令,则在写入命令后关闭 OutputStream(使用 Socket.shutdownOutput())。

如果您想在单个套接字连接上发送多个命令,那么您需要想出一种分隔每个命令的方法 (simple example here)。

关于java socket InputStream 在客户端和服务器上挂起/阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12189338/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com