首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

c/s通信或线程通信有关问题

2011-12-12 
c/s通信或线程通信问题先贴代码再说服务器端代码importjava.awt.event.*importjava.io.*importjava.net.

c/s通信或线程通信问题
先贴代码再说
服务器端代码

import   java.awt.event.*;
import   java.io.*;
import   java.net.*;
import   java.util.*;

class   Customer   extends   Object   implements   Serializable
{
String   custName,   custPwd;
}
public   class     AppServer   implements   Runnable
{
//建立一个ServerSocket   对象   ,注意没有初始化
ServerSocket   serverSocket;
Socket   client;
Thread   serverThread;

public   AppServer()
{

try
{//ServerSocket对象初始化
serverSocket   =   new   ServerSocket(1001);
serverThread   =   new   Thread(this);
serverThread.start();
}
catch   (IOException   e)
{
fail(e,   "不能启动服务器 ");
}
System.out.println( "服务器开始运行..... ");
 
}
public   static   void   fail(Exception   e   ,   String   Str)
{
System.out.println(Str   +   "   .   "   +   e);
}
public   void   run()
{
try
{
while(true)
{
Socket   client   =     serverSocket.accept();
Connection   con   =   new   Connection(client);
}
}
catch   (IOException   e)
{       //调用自定义的fail方法
fail(e,   "没有监听 ");
}
}
public   static   void   main(String[]   args)  
{
//声明一个对象
new   AppServer();
}
}

class   Connection   extends   Thread
{
Socket   netClient;
ObjectInputStream   fromClient;
PrintStream   toClient;
Customer   clientMessage;

static   Vector   vector   =   new   Vector(1,1);
        static   int   messageCount;//To   count   the   total   number   of   messages        
                                                        //stored
        private   int   localMsgCount;//   To   count   local   messages  


public   Connection(Socket   client)
{
netClient   =   client;

try
{
//   用来获得客户端传过来的信息
fromClient   =   new   ObjectInputStream(client.getInputStream());
//   用来向向客户端写出信息
toClient   =   new   PrintStream(client.getOutputStream());
}
catch   (IOException   e)
{
try
{
netClient.close();
}
catch   (IOException   el)
{
System.out.println( "不能建立流     "+   el);
return   ;
}
}
this.start();
}
public   void   run()
{

try
{
clientMessage   =   (Customer)fromClient.readObject();

//toClient.print(clientMessage.custName+ "   Connected ");
//System.out.println(clientMessage.custName);

for(;;)
{
System.out.println( "yes ");
clientMessage   =   (Customer)fromClient.readObject();//(1)
System.out.println( "no ");


if(clientMessage   ==   null)
System.out.println( "no ");
writeMessage(clientMessage);//store   message
            String   message=readMessage();//read   messages   stored
            toClient.print(message);
toClient.println( "接收来自   "+   clientMessage.custName   +   "   的数据 ");
System.out.println( "接收到了来自   "+   clientMessage.custName   +   "   的数据 ");
System.out.println( "用户:     "+   clientMessage.custName);
System.out.println( "密码:     "+   clientMessage.custPwd);
}
}
catch   (IOException   e)
{
}
catch   (Exception   el)
{
System.out.println( "读取   "+el+ "   对象时错误 ");
}
finally
{
try
{
netClient.close();
}
catch   (IOException   e)
{
}
}

}

  synchronized   void   writeMessage(Customer   cust)
      {
              vector.addElement(cust);
              ++messageCount;
              ++localMsgCount;
              notifyAll();
      }
        //Method   to   retrieve   message
      synchronized   String   readMessage()
      {
              String   str= "   ";
              while(localMsgCount> =messageCount)
              {
                      try
                      {
                          wait();
                      }
                      catch(InterruptedException   e)
                        {System.out.println( "Customer   class   could   not   be   found ");}
              }
              for(int   i=localMsgCount;i <=messageCount;   i++)
              {
                      str=str+vector.elementAt(i);
              }
              notifyAll();
              return   str;
      }
}


客户端代码

import   java.awt.event.*;
import   java.io.*;
import   java.net.*;
import   javax.swing.*;
import   java.awt.*;

class   Customer   extends   Object   implements   java.io.Serializable
{
String   custName,   custPwd;
}

public   class   CustomerApplet   extends   JApplet


{
      int   custAge;
      int   flag   =   0;
      static     JPanel   po;

      JLabel   j1,j2,j3,j4,   j5;
      JButton   buttonAccept;
      JTextField   tname,tno,tage;
      JComboBox   cpack;
      JPasswordField   pwd;

      public   void   init()
      {
        po   =   new   JPanel();
        getContentPane().add(po);
          j1   =   new   JLabel( "姓名: ");
          j2   =   new   JLabel( "号码: ");
          j3   =   new   JLabel( "年龄: ");
          j4   =   new   JLabel( "package:   ");
  j5   =   new   JLabel( "密码:   ");
          buttonAccept   =   new   JButton( "接受 ");    
  pwd   =   new   JPasswordField(15);

          tname   =   new   JTextField(20);
          tno   =   new     JTextField(15);
          tage   =   new   JTextField(2);
          String   pack[]   =   { "Exec ", "Standard "};
          cpack   =   new   JComboBox(pack);
         

          po.add(j1);
          po.add(tname);

  po.add(j5);
          po.add(pwd);
  pwd.setEchoChar( '* ');

          po.add(j2);
          po.add(tno);
         
          po.add(j3);
          po.add(tage);
         
          po.add(j4);
          po.add(cpack);      

  //添加 "接受 "按钮
  po.add(buttonAccept);
  LoginAction   la   =   new   LoginAction();
  buttonAccept.addActionListener(la);
       
        }


class   LoginAction   implements   ActionListener
{
public   void   actionPerformed(ActionEvent   evt)
{
Object   obj=   evt.getSource();
if(obj   ==   buttonAccept)
{
Customer   data=   new   Customer();
//data.custName   =   tname.getText();
//data.custPwd   =   new   String(pwd.getPassword());
data.custName   =   "1 ";
data.custPwd   =   "1 ";
try
{
Socket   toServer;
//注意:在不同的机器上面要修改成对应的IP

toServer   =   new   Socket( "127.0.0.1 ",1001);
ObjectOutputStream   streamToServer   =   new   ObjectOutputStream(toServer.getOutputStream());

streamToServer.writeObject((Customer)data);



BufferedReader   fromServer   =   new   BufferedReader(new   InputStreamReader(toServer.getInputStream()));


//String   status   =   fromServer.readLine();   (5)
System.out.println( "000 ");
//System.out.println(status);(6)
//getAppletContext().showStatus(status);(7)

streamToServer.close();
fromServer.close();


}
catch   (InvalidClassException   e)
{
getAppletContext().showStatus( "Customer类无效   "+   e);
}
catch   (NotSerializableException   e)
{
getAppletContext().showStatus( "对象没有序列化   "+   e);
}
catch   (IOException   e)
{
getAppletContext().showStatus( "不能写入到服务器端   "+   e);
}



}
}
}
}


问题有两个   (a)   如果按照现在的代码运行的话,客户端会正常的把序列化后的对象传给服务器端,但是服务器端不能正常接受每个对象,也就是在服务器端会输出   yes,   但不会输出   no   。为什么?
(b)   如果将客户端代码的(5)的注释去掉,会造成客户端程序的无响应(死掉),why?



[解决办法]
(a) 服务器端不能接受对象是因为客户端每次创建一个客户连接只发送一次object,但被server端的Connection Class里的
public void run() {
try {
clientMessage = (Customer) fromClient.readObject();
这一句接受掉了。
进入for循环后第二次试图接受object
for (;;) {
System.out.println( "yes ");
clientMessage = (Customer) fromClient.readObject();// (1)
自然接受不到东西了,于是server端的该条客户连接线程阻塞于此。而由于客户端连接已关闭,客户端再次发送的object,不管是不是来自原来的同一客户端,都回创建新的客户连接线程,不会再向该阻塞线程发送object。

(b)由于(a),server不会回应客户端message,所以客户端读message那一句uncomment后就会阻塞在那里。其实即使把(a)改好(即去掉第一次读object语句),问题(b)依然存在,因为server connection线程在readMessage里用wait挂起,再不会运行到发回message的语句。wait的锁是当前connection的实例,如果有其他客户端连上来从而触发notifyAll是通知等待新connection实例锁的进程,所以老conncetion线程永不被唤醒。

一些错误使得于我不能完全读明白这个程序的需求。有点像要实现每次提交后返回已经登录人名单功能吧,又有点像实现 "群组通话 "功能,所以也不知道怎么提改进建议.

热点排行