java socket InputStream se bloque/bloque sur à la fois le client et le serveur
Salut, toutes les
Je suis récemment travaillé sur un tout petit programme destiné à fermer le navigateur à distance.
Les procédures de base sont les suivantes:
Côté serveur:
- Créer un SocketServer à écouter certains de certains de port.
- Accepter une connexion et de créer une prise correspondante de l'objet
- Lire la InputStream de la création de la socket(bloqué sur ce
fonctionnement)
Côté Client:
- Créer une socket pour établir une connexion avec le serveur.
- Envoyer la commande pour fermer le navigateur sur le côté Serveur par l'écriture
octets de OutputStream. - Lire les réactions du serveur en utilisant read() sur InputStream de
le support(bloqué sur cette opération).
Code Ci-Dessous:
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));
}
}
}
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();
}
}
}
}
et enfin, 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();
}
}
De réitérer les problèmes:
- Le côté Serveur ne peut pas lire de la commande par l'appel read(buffer,
offset, len) sur InputStream objet de la douille. Il bloque. - Le côté Client ne peut pas lire les commentaires en appelant read(buffer,
offset, len) sur InputStream objet de son support. Il bloque. - Mais quand je commenter les commentaires de lecture dans
Client.java, à la fois Client et Serveur fonctionne correctement.
Je suis demande ce que les causes cachées dans ces codes ?
J'espère que quelqu'un peut m'aider, merci beaucoup !
OriginalL'auteur destiny1020 | 2012-08-30
Vous devez vous connecter pour publier un commentaire.
Votre socket lecture de code est la lecture jusqu'à ce que les expressions du FOLKLORE. vous ne recevrez pas EOF jusqu'à la fermeture de la socket. par conséquent, votre code ne jamais produit.
si vous souhaitez envoyer une commande unique sur la connexion de socket, puis fermez le OutputStream après l'écriture de la commande (à l'aide
Socket.shutdownOutput()
).Si vous voulez envoyer plusieurs commandes sur une seule connexion de socket, alors vous aurez besoin de trouver un moyen de la délimitation de chaque commande (exemple simple ici).
avez-vous essayé ma suggestion? la fermeture de la outputstream est indépendante de la fermeture de la inputstream.
Oui, j'ai essayé votre suggestion, j'ai ajouter une ligne os.close(), à partir de mac os.write() dans Client.java. Mais il existe une exception lorsque j'ai essayé d'appeler dans.méthode read (): Socket fermée, peut-être fermer le sous-jacent OutputStream d'une manière indirecte, à proximité de la connexion de socket ? Je suis confus sur ce point. Merci pour votre réponse !
Je ferme le flux de sortie avec sa propre méthode close (), en fait prise.shutdownOutput() doit être appelée au lieu de cela, j'ai pensé à elle. Merci pour votre suggestion, ça déchire!
ah, désolé, sera mise à jour de ma réponse. je pensais que la fermeture de la outputstream directement a la manière de le faire. depuis un certain temps, j'ai travaillé avec des sockets.
OriginalL'auteur jtahlborn
Vous lisez jusqu'à l'EOS aux deux extrémités, ce qui est un mauvais choix, car vous ne pouvez pas "envoyer", l'EOS sans perdre la possibilité d'envoyer plus de données sur la même connexion. Vous avez besoin de remodeler votre protocole d'application de sorte que vous pouvez lire une commande à un moment, sans que la connexion sera fermée pour le compléter. Par exemple, envoyer des lignes, ou à une longueur de mot préfixe, ou une auto-description de protocole tel que XML ou Java Sérialisation d'un Objet, ou ce que vous pouvez lire via DataInputStream sans compter sur EOFException.
OriginalL'auteur user207421