0

我正在尝试构建一个应用程序,其中服务器是银行,客户端是该银行的分支,因此它是经典的多线程服务器/客户端应用程序。第一步,我希望银行记录连接到它的每个分行。所以我想将布兰克作为对象发送到套接字的对象流中,以便银行可以提取并记录它。

这是我到目前为止所做的

import java.io.IOException;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


public class Banque {
private List<Succursale> listSucc = new ArrayList<Succursale>();
private int sommeTotale;
private int nbSuccInit = 4;

public void ajouteSucc(Succursale suc){

}
public Banque(){
    initialiserServeur();       
}
private void initialiserServeur() {
    ServerSocket serverSocket = null; 
    try { 
        serverSocket = new ServerSocket(10118); 
    } 
    catch (IOException e) 
    { 
        System.err.println("On ne peut pas ecouter au  port: 10118."); 
        System.exit(1); 
    }
    System.out.println ("Le serveur est en marche, Attente de la connexion.....");
    int i = 0;
    while(i<5){
        try {
            UtilMultiTh mt = new UtilMultiTh(serverSocket.accept());
            Thread t = new Thread(mt);
            t.start();
            listSucc.add(mt.getSuc());
            System.out.println(listSucc.size());

            for(int j =0; j<listSucc.size();j++){
                System.out.println("La succursale "+(j+1)+" est:"+listSucc.get(j).getName());
            }
            i++;
            System.out.println("FLAGPOSTban");
        } 
        catch (IOException e) 
        { 
            System.err.println("Accept a echoue."); 
            System.exit(1); 
        } 
    }


    System.out.println ("connexion reussie");
    System.out.println ("Attente de l'entree.....");

}
public static void main (String [] args){
    Banque banK = new Banque();
}

}

管理分支的多线程连接的 MultiTh 类

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.*;

public class UtilMultiTh implements Runnable {

private Socket soc;
private Succursale suc;
public UtilMultiTh(Socket s){
    System.out.println("FLAGconsmth");
    this.soc = s;
    }
public void run() {
    System.out.println("FLAGPOSrun");
    ObjectOutputStream oos;
    ObjectInputStream ois;
    try{            
        oos = new ObjectOutputStream(soc.getOutputStream());
        ois = new ObjectInputStream(soc.getInputStream());

        //System.out.println("La succ est");
        try {
            Object o = ois.readObject();
            if(o!=null){
                suc = (Succursale)o;
                //System.out.println("La succ est"+suc.getName());
            }
            /*while(o!=null){
                suc = (Succursale)o;
                System.out.println("La succ est"+suc.getName());
            }*/
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        oos.close();
        ois.close();
        soc.close();
    } catch (IOException e1) {
        e1.printStackTrace();
    } 
}
public synchronized Succursale getSuc() {
    return suc;
}
public void setSuc(Succursale suc) {
    this.suc = suc;
}

}

这是分支的 Succursale 类

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

public class Succursale implements Serializable {
private String coordonnees;
private String name;
private int sommeDepart;
private int sommeRecue;
private int sommeEnvoyee;
private List<Succursale> listSuccAc = new ArrayList<Succursale>();
private GuiSuccursale succView;

public Succursale (){
    succView = new GuiSuccursale(Constantes.sommeDepart,1);
    this.sommeDepart=Constantes.sommeDepart;
    this.name="Succursale: "+(1);
    connexionBanque();
}
public void connexionBanque(){
    String host = Constantes.adrBanque[0];
    int port = Constantes.portBanque[0];
    Socket echoSocket = null;
    try {
        echoSocket = new Socket(host, port);
        ObjectOutputStream oos = new ObjectOutputStream(echoSocket.getOutputStream());
        oos.writeObject(this);
        System.out.println("FLAGPOSTSUcc");
    } catch (UnknownHostException e) {
        System.err.println("Hôte inconnu: " + host);
        System.exit(1);
    } catch (IOException e) {
        e.printStackTrace();
        System.err.println("Ne pas se connecter au serveur: " + host);
        System.exit(1);
    }
}
public void connexionSuccursales(){

}
public void envoiManuel(){

}
public String getName() {
    return name;
}
public void envoiPeriodique(){

}
public static void main (String[] args){
    Succursale suc = new Succursale();
}
}

我有两个问题,我如何从 UtilMultuTh 返回一个 Succursale 到 Banque,在此之前为什么在 UtilMultiTh 类中 readObject 返回 null 而在建立连接之后我将类放入套接字中的 succursale 类?我必须在这里放一个无限循环吗?

编辑:我更改了代码,现在 multith 正确地从套接字获取 Succursale,现在的问题是线程没有同步,因为 UtilMultiTh 在 Banque 想要获取 Succursale 之后得到它,我不熟悉同步,我怎么能告诉 Banque 只有在 utilMultiTh 运行后才执行 getSuccursale ?

4

2 回答 2

0

这不是你问题的答案,但它不适合评论,我认为需要说出来。

确保在每次写入后重置输出流! ObjecdtOutputStream 只写入一次对象。如果您尝试再次编写它,它只会发送一个小注释“此时将我刚才发送的那个对象再次放回输入流中。” 节省空间,但如果您的对象已更改,这些更改将无法通过。此外,发送的原始对象将被保存在双方的内存中,从而降低您的性能。重置会清除所有内容并为您提供新的开始。

另外,我会使用 Externalizable 而不是 Serializable。这使您可以控制发送的内容(尽管您必须编写一些代码)。存在一些危险,如果您编写一个引用其他对象的对象,它也会同时写入所有其他对象,这是您可能不想要的。此外,即使类发生变化,Externalizable 也允许您写入相同的旧格式。此外,它还允许您输入版本号。这些有时可以允许较新版本读取由较旧版本写入的流,但它总是会向您发出格式已更改的警告。

ObjectOutputStream 的目的是您可以编写一个包含所有数据的对象。一次调用 writeObject 就可以发送一个真正庞大的图形。这很巧妙。对我来说效果很好,将计算机游戏的完整状态写入带有 one 的磁盘文件writeObject( this ),但写入套接字时通常是一场灾难。

我有点倾向于不使用 ObjectOutput,而只是编写原语。它更简单,更快,并且您可以控制很多。但是我很难知道要在 Input 端创建哪个对象。我认为最好的办法是读取和写入对象,但通过为 Externalizable 接口编写自己的方法并reset()在每个writeObject.

于 2013-07-02T21:05:07.543 回答
0

Google 的 protobufs 非常适合这一点。我建议使用它们并在客户端和服务器之间发送字节输出。如果您打算使用 TCP,则需要对输出进行框架化。

Java 的序列化机制总是会在不同的运行时版本之间中断。另外,如果您决定用另一种语言实现服务器或客户端怎么办?您必须复制 java 的整个序列化逻辑。Protobuf 负责将对象编组和解组字节所需的繁琐过程。差不多,它是Java内置序列化的一种更好的形式,它与语言无关。

所以我建议你放弃对象流。我知道这不是您希望的答案,但从长远来看,它会让您的事情变得更好。

原型缓冲区

于 2013-07-02T20:15:01.353 回答