java多客户端/服务器。处理通讯
从两天以来,我一直在忍受着这些代码的折磨。事实上,我正在开发一个应用程序,它有服务器端和客户端。服务器每秒钟接收一次来自客户端的请求,通过联系数据库处理请求,然后将结果发送回客户端。
我这样做的方式是,如果客户端在服务器之前启动,它将继续尝试连接到给定端口和给定主机上的服务器
1.这是服务器端:
try
{
Client client = new Client(jTable1,jLabel3);
Thread t = new Thread(client);
t.start();
}catch(IOException e){}
类客户端。爪哇
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。爪哇
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){}
}
这是使我的服务器运行的两个类。类客户端。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循环接受线程中的连接
-客户端。在另一个线程中,每次尝试联系服务器以建立连接
-在另一个线程中,客户端再次向服务器发送请求
-服务器是另一个从数据库请求信息并发送回客户端的线程
我非常感谢你的帮助
# 1 楼答案
这很简单,但底层技术很复杂 我的解释顺序与我的回答相反
在主代码中,使用GrizzlyServerFactory启动Grizzlyserver。创建(url),它侦听“127.0.0.1”
当服务器启动时,它会搜索带有注释@Path的类。。。找到“你的服务”
因此Grizzly将在url“http://127.0.0.1/FUNNY_SERVICE_V001”上“注册”(或类似的内容)ServiceClass“YourService”(参见I_ServiceCommons)
嗯。。我们又进入了主代码。我们创建一个MyRequest对象,并创建一个具体服务“service”的实例。更好的名称应该是“ServiceClient”,因为它是客户端的代码。“服务”是用url(“http://127.0.0.1”)创建的,并逐步进入AbstractClient中的公共构造函数代码(用于所有客户端),并创建服务url“http://127.0.0.1/FUNNY_SERVICE_V001”。在AbstractClient内部,将创建一个客户端对象(用于连接/编码处理等)。 当我们想要访问服务器时,我们只需要将MyRequest对象放入“服务”的“getResult”方法中。AbstractClient中的客户端将MyRequest对象转换为XML重新表示(注意其中的@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注释进行注释(在客户机中,我们使用HTTP-POST)。您可以处理MyRequest对象,必须返回一个MyResult对象,该对象将转换为xml,由客户端发送、接收并重新创建为MyResult对象。就这样# 2 楼答案
哦,用打印机等把所有东西都放在低电平插座上是个坏主意。 我在过去遇到过几个编码和多线程错误。因此,我的解决方案(当然有点慢,但很容易使用)是:Jersey&;灰熊
最大的优点是:您可以非常轻松地修改和扩展传输对象,而无需修改传输代码(低级套接字写入)
一个接口
服务器端代码
你的客户
您的服务客户端
你的转让对象
最后