Ma question est très simple. Je veux juste utiliser une prise d'objet client à nouveau.
Généralement, les gens créent une nouvelle prise à tout moment le client tente de connecter le serveur tel: p> après le premier WriteObject je veux à nouveau envoyer plus d'informations au serveur en réutilisant Out.writeObject (NextObject), mais le serveur n'est plus atteint. Pour que cela fonctionne, je dois passer à travers toutes les étapes ci-dessus. Pourquoi? P> Voici le code que j'utilise pour tester ce que je voulais dire. Le code après "Deuxième demande ne" pas ... "n'atteint pas le serveur. Toutefois, si je supprimais les commentaires juste au-dessus de ces commentaires, cela passera. Pourquoi ne peut-il pas réutiliser le même objet de socket client sans avoir à utiliser une nouvelle prise (). P>
Class Hello -> Data passed between the server and the client
Class TestClient -> Client
Class TestServer -> Server
package tests;
import java.io.Serializable;
public class Hello implements Serializable {
String hola = "hello my friend";
public String getHello () {
return hola;
}
public void setHello (String str) {
hola = str;
}
}
package tests;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class TestClient {
public static void main(String[] args) {
try {
ObjectOutputStream clientOutput;
ObjectInputStream serverInput;
Hello goingout = new Hello ();
Socket client = new Socket ("localhost", 5555);
clientOutput = new ObjectOutputStream (client.getOutputStream());
serverInput = new ObjectInputStream (client.getInputStream());
clientOutput.writeObject(goingout);
clientOutput.flush();
Hello comingin = (Hello) serverInput.readObject();
System.out.println ("first time received: " + comingin.getHello());
/*
* Socket client = new Socket ("localhost", 5555);
clientOutput = new ObjectOutputStream (client.getOutputStream());
serverInput = new ObjectInputStream (client.getInputStream());
*/
/*
* Second request doesn't got through the server
*/
comingin.setHello("again");
clientOutput.writeObject(goingout);
clientOutput.flush();
comingin = (Hello) serverInput.readObject();
System.out.println ("second time received: " + comingin.getHello());
} catch (ClassNotFoundException ex) {
System.out.println (ex.getMessage());
} catch (UnknownHostException ex) {
System.out.println (ex.getMessage());
} catch (IOException ex) {
System.out.println (ex.getMessage());
}
}
}
public class TestServer {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(5555, 100);
ObjectInputStream clientInput;
ObjectOutputStream serverOutput;
for (;;) {
System.out.println ("Listening for connections");
Socket fromClient = server.accept();
serverOutput = new ObjectOutputStream (fromClient.getOutputStream());
clientInput = new ObjectInputStream (fromClient.getInputStream());
Hello received = (Hello) clientInput.readObject();
serverOutput.writeObject(received);
serverOutput.flush();
}
} catch (ClassNotFoundException ex) {
Logger.getLogger(TestServer.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(TestServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
4 Réponses :
Le problème est que la déclaration de socket declient = serveur.accept (); code> sur le serveur est à l'intérieur de la portée du
pour code> boucle. Donc, à la fin du
pour code> boucle (après
ServerOutput.flush (); code>) Le
fromClient code> La variable est détruite et une nouvelle est créée le La prochaine fois que la boucle commence. Vous devrez vous restructurer comme ceci si vous souhaitez que la même connexion soit capable d'envoyer / recevoir plusieurs messages:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.HashMap
public class User extends Runnable
{
public String username;
public Socket socket;
public TestServer testServerReference;
ObjectInputStream clientInput;
ObjectOutputStream serverOutput;
public User(Socket s, TestServer tS)
{
socket = s;
testServerReference = tS;
}
/**
* Creates the in/out Streams, returns the username
*/
public String init()
{
serverOutput = new ObjectOutputStream (fromClient.getOutputStream());
clientInput = new ObjectInputStream (fromClient.getInputStream());
this.username = (String)clientInput.readObject(); //the first thing the client should send is a username
}
public void run()
{
try
{
//add send/receive logic here for connected client
}
catch (Exception ex)
{
}
finally
{
testServerReference.removeUser(username);
}
}
}
public class TestServer {
public static HashMap<String,User> userList = new HashMap<String,User>();
public static void main(String[] args)
{
try {
ServerSocket server = new ServerSocket(5555, 100);
while (true) //start accepting new connections
{
System.out.println ("Listening for connections");
Socket fromClient = server.accept();
User newUser = new User(fromClient,this);
String newUsername = newUser.init();
userList.add(newUsername,newUser);
(new Thread(newUser)).start();
}
} catch (ClassNotFoundException ex) {
Logger.getLogger(TestServer.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(TestServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void removeUser(String username)
{
userList.remove(username);
}
}
Bonjour AIOI222, merci pour la réponse, mais ce n'est pas ce que je cherche. Le serveur.accept doit être dans la boucle pour les empiler lorsque de nombreuses demandes de client sont envoyées au même serveur en même temps. Le problème ici est que cela signifie que "New ObteInputStream" doit être effectué dans la boucle, ce qui signifie que le client de l'autre côté ne sait pas que sa sortie est maintenant perdue, envoyant le message à personne non-un.
HMM vient de réaliser que les problèmes proviennent du fait que le socket est ré-écrit par conséquent du point de vue du client, l'autre extrémité ne répond plus. Doit trouver la solution et le poster ici
Il y a un certain nombre de solutions à cela. Chaque fois qu'un nouvel utilisateur se connecte, vous devrez économiser cette prise et les flux associés à une liste. Vous pouvez ensuite accompagner un nouveau fil d'auditeur pour chaque connexion qui gère l'envoi / la réception de messages pour la prise associée. Une autre option consiste à disposer d'un seul fil qui écoute pour les nouvelles connexions et un seul thread qui iTère à travers toutes les connexions et les vérifie pour une nouvelle entrée et les envoie une nouvelle sortie. Une troisième option serait de définir des tempêtes sur les sockets et l'accepteur de socket et tout faire à partir d'un seul fil.
Le serveur que j'ai en réalité crée un threads par client différent, puis ce client parle toujours de ce fil dans une prise différente de celle de la première instance. Donc, ce problème est trié. Celui qui n'est pas trié est lorsque ce client envoie également plusieurs demandes. Vous devez accepter l'acceptation dans la boucle pour les faire la queue lorsque le serveur ne peut pas les servir tout en même temps. Un autre problème serait d'abord analyser les données, vérifiez quel utilisateur est, puis lisez dans la liste la prise correspondante. C'est sur-ingénierie, je crois.
J'ai édité ma réponse originale avec un exemple de code que je pense correspond à votre problème un peu mieux. Il est basé sur le code que vous avez posté ci-dessous.
Merci, je n'ai pas vu votre solution. Je vais regarder ça. Merci beaucoup pour votre aide.
Je pense que la réponse est ici: http://docs.oracle.com/javase/1.4.2/docs/apl /java/net/serversion.html#accept%28%29 . P>
Il ne peut tout simplement pas être fait lorsque vous avez un serveur assistant à plusieurs clients. Server.accept crée une nouvelle prise de sorte que le client perd la connexion avec la prise du serveur créé à première instance, car cela écrase l'objet de la prise. p>
Vous ne pouvez pas accepter l'acceptation de la boucle car cela signifie que le serveur n'écoute qu'un seul client. Vous pourrez peut-être jouer avec deux instances, mais cette solution ne serait disponible que pour un serveur en écoutant plusieurs demandes d'un client uniquement. P>
En résumé, il ne peut pas être fait d'où tout l'exemple sur le Net utilise un nouveau socket () au client à tout moment, il tente d'envoyer de nouvelles informations au serveur, même si le client est identique. p>
Ceci est une erreur. Il est possible d'avoir plusieurs clients connectés et d'envoi de messages / réception sans la nécessité de recréer la prise à chaque fois. Je recommanderais d'obtenir Google et de rechercher un simple client / serveur de chat basé sur Java.
Ceci est différent. Il n'y a pas de serveur.accept qui crée une nouvelle prise. LIVELINE coule les informations sur la même prise tout le temps. Cela n'a rien à faire.
Désolé, il suffit de frapper le clavier :). Afin de trouver une solution, je dois être capable de passer le contexte de la prise écrite sur la prise en contact avec le client. À ce stade, je dois évaluer si une telle solution est meilleure que de les écraser.
Il est possible qu'un serveur assister à plusieurs clients. Chaque prise de serveur doit être traitée par son propre thread. Le serveur écoute sur une prise connu et chaque client se connecte à l'aide d'une prise distincte (de sorte que plusieurs clients peuvent s'exécuter sur le même hôte). p>
Tout d'abord, les Javadocs sont l'un des pires endroits pour comprendre comment ou pourquoi em> vous devez utiliser une bibliothèque, ils ne vous disent vraiment que ce que em> la bibliothèque fait . P>
Votre message que ce n'est pas possible n'est vrai que si vous restez avec un serveur à filetage unique . P>
Oracle a une page sur sockets de serveur Java qui explique plusieurs clients (avec réutilisation) avec un seul serveur. p>
Ils ont aussi un Page des sockets avancés qui passe plus en détail. p>
Salut Kelly French. Merci. Mon serveur est déjà multi-threadé. Un client parle toujours à un fil séparé pour toujours jusqu'à ce que l'un des deux décident d'arrêter la conversation. La seule façon de faire est de passer le contexte de prise écrasé sur la prise d'origine (première connexion du fil avec le client). Je vais devoir faire une telle chose.
Si vous partagez une prise entre plusieurs threads, il n'est plus multi-fileté de la manière dont nous voulons dire. Oui, il peut encore avoir plusieurs threads, mais la prise partagée entraîne une convention typique des programmes filetés, tels que la question de votre question où un thread ferme une prise partagée par un deuxième fil. Un serveur multi-threadé indique généralement que chaque thread a sa propre connexion de socket et ne partage pas.
Ok les gens. Merci à AOI222 et à Kely français principalement, mais grâce à quelqu'un d'autre. J'ai trouvé la solution qui est:
1.- Évidemment, vous devez créer un fil qui sert un client exclusivement. Première fois que le client se connecte au serveur à un port général. Ceci crée un fil d'écoute d'un port particulier et laissez le client savoir quel nouveau port, le nouveau fil à écouter. Ensuite, le client change de port et crée une nouvelle prise pour démarrer la conversation avec le client. P>
2.- Le serveur, fonctionnant comme un thread séparé, doit continuer à écouter une boucle comme AOI222 indiquée pour toujours. L'acceptation est juste hors de la boucle pour le fil exclusif qui a été attribué à un client. Veuillez consulter le code ci-dessous et désolé pour le nom des variables car ils sont un peu déroutant: p> 3.- S'il vous plaît voir que le serveur de fil principal doit avoir la serveur.accept dans la boucle afin d'accepter la nouvelle connexion des clients p> "exclusivethread" est un fil qui implémente le code dans 2. P> Merci beaucoup pour votre aide. P> P>
Peut-être que le serveur ferme la connexion? Pouvez-vous nous montrer le code du serveur?
Peut-être que le serveur ne comprend pas les informations envoyées et la fermeture de la prise. Qu'est-ce qui est contenu dans les journaux du serveur?