0

自从两天以来,我一直在受这些代码的困扰。事实上,我正在开发一个具有服务器端和客户端的应用程序。服务器每秒接收来自客户端的请求,通过联系数据库处理请求,然后将结果发送回客户端。我这样做的方式是,如果客户端在服务器之前启动,它将继续尝试连接到给定端口和给定主机上的服务器。
1.这是服务器端:

try
    {   
        Client client = new Client(jTable1,jLabel3);
        Thread t = new Thread(client);
        t.start();

    }catch(IOException e){}

类 Client.java

public class Client implements Runnable{

private int svrPort = 0;
ServerSocket serverConnect = null;
static  Socket clientSocket = null;
static  ClientConnectThread t[] = new ClientConnectThread[1000];
JTable jtable;
JLabel jlabel;

public Client(JTable table, JLabel label) throws IOException {

    this.svrPort = 9450;
    this.jtable = table;
    this.jlabel = label;

}

public void run(){
    try{
        serverConnect = new ServerSocket(this.svrPort);

    }catch(IOException e){}
    while(true){
        try{
            clientSocket = serverConnect.accept ();
            for(int i=0; i<=1000; i++){ //I can accept up to 1000 clients
        if(t[i]==null)
        {
            (t[i] = new ClientThread(client, t, jtable, jlabel)).start();
                        System.out.println ("Etat12. Apres bloc try");
            break;
        }
    }
        }catch(IOException e){}
    }
}

}

类 ClientThread.java

public ClientThread(Socket socket, ClientThread t[], JTable table, JLabel label){

    this._socket = socket;
    this.jTable = table;
    this.jlabel = label;
    this.totalConnected = 0;       
    this.t = t;
}

public void run(){

    int index = 0;
    try{
        this._output = new PrintWriter(this._socket.getOutputStream ());
        this._input = new BufferedReader(new InputStreamReader(this._socket.getInputStream()));

        while((clientMsg = this._input.readLine ()) != null){
            if(clientMsg.equals ("@CONNECT")){ // If it is the first time the user is signig in, fill the table

                jTable.setValueAt (this._socket.getInetAddress (), index, 0);
                jTable.setValueAt (new Date(), index, 1);
                jTable.setValueAt (new Date(), index, 2);
                totalConnected++;
                jlabel.setText ("");
                jlabel.setText (totalConnected+"");

            }else if(Integer.parseInt (clientMsg) == 1){
                int p = Integer.parseInt (clientMsg);
                this._output = new PrintWriter(this._socket.getOutputStream(), true);
                if (this.getData.connect ())
                {
                    if(this.getData.getDataByType (1).size () == 0){
                    }
                    _output.println (this.getData.getDataByPeriod (1));
                }else{System.out.println("You are not connected to the database server");}

            }else if(Integer.parseInt (clientMsg) == 2){
                int p = Integer.parseInt (clientMsg);
                this._output = new PrintWriter(this._socket.getOutputStream(), true);
                if (this.getData.connect ())
                {
                    if(this.getData.getDataByPeriod (2).size () == 0)System.out.println ("There is no data corresponding");
                    this._output.println (this.getData.getDataByPeriod (2));
                }else{System.out.println("You are not connected to the database server");}


            }else if(Integer.parseInt (clientMsg) == 3){
                int p = Integer.parseInt (clientMsg);
                this._output = new PrintWriter(this._socket.getOutputStream(), true);
                if (this.getData.connect ())
                {
                    if(this.getData.getDataByType (3).size () == 0)System.out.println ("There is no data corresponding");
                    this._output.println (this.getData.getDataByType (30));
                }else{System.out.println("You are not connected to the database server");}


            }else if(Integer.parseInt (clientMsg) == 4){
                int p = Integer.parseInt (clientMsg);
                this._output = new PrintWriter(this._socket.getOutputStream(), true);
                if (this.getData.connect ())
                {
                    if(this.getData.getDataByType (4).size () == 0)System.out.println ("There is no data corresponding");
                    this._output.println (this.getData.getDataByType (60));
                }else{System.out.println("You are not connected to the database server");}


            }else{

            }
        }
        this._input.close ();
        this._output.close ();
    }catch(IOException e){}

}

这是使我的服务器运行的两个类。Client.java 类启动并等待接受连接。当客户端连接时,会创建一个 clientThread 实例并将其关联到客户端。直到这里,一切似乎都运行良好。

客户端

public class ServerConnect implements Runnable{

public static Socket clientSocket = null;
public static PrintWriter out = null;
public static BufferedReader in = null;
public static int port=9450;
public static String host = "127.0.0.1";
public static JLabel myLabel;
public static JButton button;
public static ResourceMap resourceMap;
private static String serverMsg = "";

public ServerConnect(JLabel jLabel, JButton b)
{
    jLabel.setText ("Trying to contact the server");
    myLabel = jLabel;
    button = b;
    port = Integer.parseInt("9450");
    host = "127.0.0.1";

        try{
            clientSocket = new Socket(host, port);
            }catch(IOException e){e.printStackTrace ();}

}

public void run()
{
    while(true){
        while(!this.connect ())
        {myLabel.setText ("You are not connected to the server : "+host);
         button.setEnabled (false);
            try{
                clientSocket = new Socket(host, port);
            }catch(IOException e){}
        }

        myLabel.setText ("You are connected to the server : "+host);
        button.setEnabled (true);
        try{
           out = new PrintWriter(clientSocket.getOutputStream(), true);
           out.println("@CONNECT");

           in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
           while((serverMsg = in.readLine ()) != null){
                System.out.println ("<=> :"+serverMsg);
           }
        }
        catch(IOException e){e.printStackTrace ();}
    }
}
private boolean connect()
{
    try{
        clientSocket = new Socket(host, port);
        return true;
    }catch(IOException e){}
    return false;
}}

我的问题是,当双方启动时,客户端发送@CONNECT 的唯一内容,服务器接收它并全部停止在这里。如果客户端再次发送请求,服务器将不响应。
我希望有人逐步向我展示如何设置此应用程序
- 服务器端。接受带有 WHILE 循环的线程中的连接
- 客户端。在另一个线程中每次尝试联系服务器以建立连接
- 在另一个线程中,客户端再次向服务器发送请求
- 服务器是另一个线程从数据库中请求信息并发送回客户端。

我非常感谢你的帮助

4

2 回答 2

1

哦,用 PrintWriter 等将所有内容放到低级套接字上是个坏主意。过去我遇到了几个编码和多线程错误。所以我的(当然慢一点,但易于使用)的解决方案是:Jersey & Grizzly。

最大的优点是:您可以非常轻松地修改和扩展您的传输对象,而无需修改您的传输代码(低级套接字编写)

一个界面...

public interface I_ServiceCommons {
        public static final String  MEDIATYPE           = "text/xml";
        public static final String  MEDIATYPE_ENCODING  = I_ServiceCommons.MEDIATYPE + "; charset=utf-8";
        public static final String SERIVCENAME = "/FUNNY_SERVICE_V001";
    }

服务器端代码

@Path(I_ServiceCommons.SERIVCENAME)
public class YourService {

    @POST
    @Produces(I_ServiceCommons.MEDIATYPE)
    @Consumes(I_ServiceCommons.MEDIATYPE)
    public ResultObject request(final RequestObject yourRequest) {
        //process here your request in Server
    }
}

你的客户……

public class abstract YourAbstractClient{
        protected Logger                            log             = Logger.getLogger(this.getClass());
        protected final String                      serviceUrl;
        private final WebResource                   resource;

        public YourAbstractClient(final String url) {
            this.serviceUrl = url + getService();
            this.resource = Client.create().resource(this.serviceUrl);
        }

        public abstract String getService();

        protected <RES, REQ> RES post(final Class<RES> resultClazz, final REQ req) {
            final Builder builder = this.resource.type(I_ServiceCommons.MEDIATYPE).accept(I_ServiceCommons.MEDIATYPE);
            try {
                final RES result = builder.post(resultClazz, req);
                return result;
            } catch (final Exception e) {
                throw new RuntimeException("Error posting data to [" + this.serviceUrl + "]: " + e.getMessage(), e);
            }
        }

    }

您的服务客户端...

public class Service extends YourAbstractClient {

    public Service(final String url) {
        super(url);
    }

    public MyResult getResult(final MyRequest req) {
        return super.post(MyResult.class, req);
    }

    @Override
    public String getService() {
        return I_ServiceCommons.SERIVCENAME;
    }
}

您的传输对象

@XmlRootElement
public class MyRequest implements Serializable {
    public void setRequestType(final int p_AequestType) {
        this.requestType = p_AequestType;
    }

    public int getRequestType() {
        return this.requestType;
    }
}

而结局...

String url = "http://127.0.0.1";
GrizzlyServerFactory.create(url) //starts the server
MyRequest res = new MyRequest();
MyResult result = new Service(url).getResult(req); // Corrected
于 2012-07-24T06:30:56.223 回答
0

这很简单——但底层技术很复杂。;) 我以相反的顺序解释它(我的答案@ https://stackoverflow.com/a/11625335/1268954)。

在主代码中,您使用 GrizzlyServerFactory.create(url) 启动 Grizzlyserver,它侦听“127.0.0.1”。

当服务器启动时,它会搜索带有注解 @Path ... 的类并找到“YourService”。

因此,Grizzly 将在 URL“ http://127.0.0.1/FUNNY_SERVICE_V001 ”上“注册”(或类似的)ServiceClass“YourService”(参见 I_ServiceCommons)。

好吧..我们再次进入主代码。我们创建一个 MyRequest 对象并创建一个具体服务“Service”的实例。更好的名称应该是“ServiceClient”,因为它是客户端的代码。“服务”是使用 URL(“ http://127.0.0.1 ”)创建的,并进入 YourAbstractClient 中的公共构造函数代码(适用于所有客户端)并创建服务 URL“ http://127.0.0.1/FUNNY_SERVICE_V001" . 在 YourAbstractClient 内部将创建一个客户端对象(用于连接/编码处理等)。当我们要访问服务器时,我们只需将 MyRequest 对象放入“服务”的“getResult”方法中。客户端在 YourAbstractClient 内部将 MyRequest 对象转换为 XML Reresentation(注意其中的 @XMLRootElement 注释、无参数构造函数和 set/get 方法)对服务器执行 HTTP POST,从而重新创建 MyRequest 对象。

所以再次在服务器端......所以当客户端以正确的方式连接到“ http://127.0.0.1/FUNNY_SERVICE_V001 ”时,服务器会创建一个YourService实例(需要无参数构造函数)并读取xml,创建transferobject MyRequest 并将其放入方法public ResultObject request(final RequestObject yourRequest)中,因为它使用@POST Annotation 进行了注释(在客户端我们执行HTTP-POST)。您可以处理您的 MyReqeust 对象,并且必须返回一个 MyResult 对象,该对象将转换为 xml,由客户端发送、接收并重新创建为 MyResult 对象。就是这样。

于 2012-07-24T08:10:06.403 回答