【转】Android 基于Socket的聊天室

原文

Socket是TCP/IP协议上的一种通信,在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路。一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信。

Client A  发信息给 Client B ,  A的信息首先发送信息到服务器Server ,Server接受到信息后再把A的信息广播发送给所有的Clients

首先我们要在服务器建立一个ServerSocket ,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状态。

Socket accept():如果接收到一个客户端Socket的连接请求,该方法将返回一个与客户端Socket对应的Socket

Server示例:

//创建一个ServerSocket,用于监听客户端Socket的连接请求
ServerSocket ss = new ServerSocket(30000);
//采用循环不断接受来自客户端的请求
while (true){
//每当接受到客户端Socket的请求,服务器端也对应产生一个Socket
Socket s = ss.accept();
//下面就可以使用Socket进行通信了
...
}

客户端通常可使用Socket的构造器来连接到指定服务器
Client示例:

//创建连接到服务器、30000端口的Socket
Socket s = new Socket("192.168.2.214" , 30000);
//下面就可以使用Socket进行通信了
...

这样Server和Client就可以进行一个简单的通信了
当然,我们要做的是多客户,所以每当客户端Socket连接到该ServerSocket之后,程序将对应Socket加入clients集合中保存,并为该Socket启动一条线程,该线程负责处理该Socket所有的通信任务

//定义保存所有Socket的ArrayList
public static ArrayList<Socket> clients = new ArrayList<Socket>();

当服务器线程读到客户端数据之后,程序遍历clients集合,并将该数据向clients集合中的每个Socket发送一次。这样就可以实现一个聊天室的功能了

下面来看看整个功能的demo

先建立一个Java工程,把Server.java运行起来,然后再运行手机模拟器

2011122916364191 2011122916370480 2011122916372998

服务器打印信息:

2011122916380590

程序文件结构:

2011122916502972

嘿嘿,大家别笑我,我的JAVA水平还是初学者,很多地方都觉得很菜,代码规格程度:小学。 有待提高啊!

1.先看看主Activity : SocketmsgActivity.java

public class SocketmsgActivity extends Activity {
     /** Called when the activity is first created. */
     private SQLiteDatabase db;
     
     Thread thread = null;
     Socket s = null;
     private InetSocketAddress isa = null; 
 
     DataInputStream dis = null;
     DataOutputStream dos = null;
     private String reMsg=null;
     private Boolean isContect = false;
     private EditText chattxt;
     private EditText chatbox;
     private Button chatok;
     
     private String chatKey="SLEEKNETGEOCK4stsjeS";
     private String name=null,ip=null,port=null;
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
         chattxt = (EditText)findViewById(R.id.chattxt);
         chatbox = (EditText)findViewById(R.id.chatbox);
         chatok = (Button)findViewById(R.id.chatOk);
         chatbox.setCursorVisible(false);
         chatbox.setFocusable(false);
         chatbox.setFocusableInTouchMode(false);
         chatbox.setGravity(2);
         
         //初始化,创建数据库来储存用户信息
         InitDatabase();
         db = SQLiteDatabase.openOrCreateDatabase(config.f, null);
         try {
             Cursor cursor = db.query("config", new String[]{"ip","name","port"},null,null, null, null, null);
             while(cursor.moveToNext()){
                 name = cursor.getString(cursor.getColumnIndex("name"));
                 ip = cursor.getString(cursor.getColumnIndex("ip"));
                 port = cursor.getString(cursor.getColumnIndex("port"));
             }
             cursor.close();
         } catch (Exception e) {
             // TODO: handle exception
             System.out.println(e.toString());
         }
         db.close();
         
         //设置连接
         if(ip==null || port==null){
             Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);
             startActivity(intent);
             SocketmsgActivity.this.finish();
         }
         //设置名称
         else if(name==null){
             Intent intent = new Intent(SocketmsgActivity.this,IniuserActivity.class);
             startActivity(intent);
             SocketmsgActivity.this.finish();
         }else{
             
             connect();
             chatok.setOnClickListener(new View.OnClickListener() {
     
                 @Override
                 public void onClick(View v) {
     
                     String str = chattxt.getText().toString().trim();
                     System.out.println(s);
                     try {
                         dos.writeUTF(chatKey+"name:"+name+"end;"+str);
                         chattxt.setText("");
     
                     }catch (SocketTimeoutException  e) {
                           System.out.println("連接超時,服務器未開啟或IP錯誤");
                           Toast.makeText(SocketmsgActivity.this, "連接超時,服務器未開啟或IP錯誤", Toast.LENGTH_SHORT).show();
                           Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);
                         startActivity(intent);
                         SocketmsgActivity.this.finish();
                           e.printStackTrace();
                       } catch (IOException e) {
                         // TODO Auto-generated catch block
                           System.out.println("連接超時,服務器未開啟或IP錯誤");
                           Toast.makeText(SocketmsgActivity.this, "連接超時,服務器未開啟或IP錯誤", Toast.LENGTH_SHORT).show();
                           Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);
                         startActivity(intent);
                         SocketmsgActivity.this.finish();
                           e.printStackTrace();
                     }
                 }
             });
         }
     }
     
     private Runnable doThread = new Runnable() {
         public void run() {
             System.out.println("running!");
             ReceiveMsg();
         }
     };   
     
     public void connect() {
         try {
             s = new Socket();
             isa = new InetSocketAddress(ip,Integer.parseInt(port)); 
             s.connect(isa,5000); 
 
             if(s.isConnected()){
                 dos = new DataOutputStream (s.getOutputStream());
                 dis = new DataInputStream (s.getInputStream());
                 dos.writeUTF(chatKey+"online:"+name);
                 /**
                  * 这里是关键,我在此耗时8h+
                  * 原因是 子线程不能直接更新UI
                  * 为此,我们需要通过Handler物件,通知主线程Ui Thread来更新界面。
                  * 
 */
                 thread = new Thread(null, doThread, "Message");
                   thread.start();
                   System.out.println("connect");
                   isContect=true;
             }
           }catch (UnknownHostException e) {
               System.out.println("連接失敗");
             Toast.makeText(SocketmsgActivity.this, "連接失敗", Toast.LENGTH_SHORT).show();
             Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);
             startActivity(intent);
             SocketmsgActivity.this.finish();
               e.printStackTrace();
           }catch (SocketTimeoutException  e) {
               System.out.println("連接超時,服務器未開啟或IP錯誤");
               Toast.makeText(SocketmsgActivity.this, "連接超時,服務器未開啟或IP錯誤", Toast.LENGTH_SHORT).show();
             Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);
             startActivity(intent);
             SocketmsgActivity.this.finish();
               e.printStackTrace();
           }catch (IOException e) {
               System.out.println("連接失敗");
               e.printStackTrace();
           }
     }
    
     public void disConnect() {
         if(dos!=null){
         try {
             
                 dos.writeUTF(chatKey+"offline:"+name);
             
         } catch (IOException e1) {
             // TODO Auto-generated catch block
             e1.printStackTrace();
         }
         try {
             s.close();
         } catch (IOException e) {
               e.printStackTrace();
         }
         }
     }
   
     
     /**
      * 线程监视Server信息
 */
     private void ReceiveMsg() {
         if (isContect) {
             try {
                 while ((reMsg = dis.readUTF()) != null) {
                     System.out.println(reMsg);
                     if (reMsg != null) {
 
                         try {
                             Message msgMessage = new Message();
                             msgMessage.what = 0x1981;
                             handler.sendMessage(msgMessage);
                             Thread.sleep(100);
                         } catch (InterruptedException e) {
                             // TODO Auto-generated catch block
                             e.printStackTrace();
                         }
 
                     }
                 }
             } catch (SocketException e) {
                 // TODO: handle exception
                 System.out.println("exit!");
             } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
 
         }
     }
   
     /**
      * 通过handler更新UI
 */
     Handler handler = new Handler() {
         public void handleMessage(Message msg) {
             switch (msg.what) {
             case 0x1981:
                 chatbox.setText(chatbox.getText() + reMsg + '\n');
                 chatbox.setSelection(chatbox.length());
                 break;
             }
         }
     };
     
     @Override
     protected void onDestroy() {
         // TODO Auto-generated method stub
         super.onDestroy();
         disConnect();
         //System.exit(0);
     }
     
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         // TODO Auto-generated method stub
         menu.add(0, 1, 1, "初始化設置");
         menu.add(0, 2, 2, "退出");
         return super.onCreateOptionsMenu(menu);
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         // TODO Auto-generated method stub
         if(item.getItemId()==1){
             Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);
             startActivity(intent);
             SocketmsgActivity.this.finish();
         }else if(item.getItemId()==2){
             disConnect();
             SocketmsgActivity.this.finish();  
             android.os.Process.killProcess(android.os.Process.myPid());
             System.exit(0);
         }
         return super.onOptionsItemSelected(item);
     }
 
     public void InitDatabase(){
          
         if(!config.path.exists()){  
             config.path.mkdirs();    
             Log.i("LogDemo", "mkdir");  
         }   
         if(!config.f.exists()){      
             try{   
                 config.f.createNewFile();  
                 Log.i("LogDemo", "create a new database file");
             }catch(IOException e){   
                 Log.i("LogDemo",e.toString());
             }   
         }  
         try {
             if(tabIsExist("config")==false){
                 db = SQLiteDatabase.openOrCreateDatabase(config.f, null);  
                 db.execSQL("create table config(_id integer primary key autoincrement," +
                         "ip varchar(128),port varchar(10),name varchar(32))");
                 Log.i("LogDemo", "create a database");
                 db.close();
             }
         } catch (Exception e) {
             // TODO: handle exception
             Log.i("LogDemo",e.toString());
         }
     }
     
     /**
      * check the database is already exist
      * @param tabName
      * @return
 */
     public boolean tabIsExist(String tabName){
         boolean result = false;
         if(tabName == null){
                 return false;
         }
         Cursor cursor = null;
         db = SQLiteDatabase.openOrCreateDatabase(config.f, null); 
         try {
             String sql = "select count(*) as c from sqlite_master where type ='table' " +
                         "and name ='"+tabName.trim()+"' ";
             cursor = db.rawQuery(sql, null);
             if(cursor.moveToNext()){
                 int count = cursor.getInt(0);
                 if(count>0){
                     result = true;
                 }
             }
                 
         } catch (Exception e) {
                 // TODO: handle exception
         }  
         cursor.close();
         db.close();
         return result;
     }
 }

2.初始化IP和端口Activity, IniActivity.java

public class IniActivity extends Activity{
 
     private EditText ip,port;
     private Button nextButton;
     private String getip,getport;
     private ProgressDialog progressDialog;
     private InetSocketAddress isa = null; 
     private SQLiteDatabase db;
     private String ipstring=null,portString=null;
     private int row=0;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         // TODO Auto-generated method stub
         super.onCreate(savedInstanceState);
         setContentView(R.layout.config);
         
         ip = (EditText)findViewById(R.id.ip);
         port = (EditText)findViewById(R.id.port);
         nextButton = (Button)findViewById(R.id.next);
         
         
         db = SQLiteDatabase.openOrCreateDatabase(config.f, null);
         try {
             Cursor cursor = db.query("config", new String[]{"ip","port"},null,null, null, null, null);
             while(cursor.moveToNext()){
                 ipstring = cursor.getString(cursor.getColumnIndex("ip"));
                 portString = cursor.getString(cursor.getColumnIndex("port"));
                 row++;
             }
             ip.setText(ipstring);
             port.setText(portString);
             cursor.close();
         } catch (Exception e) {
             // TODO: handle exception
             System.out.println(e.toString());
         }
         db.close();
         
         nextButton.setOnClickListener(new nextButtonListenner());
     }
     
     class nextButtonListenner implements OnClickListener{
 
         @Override
         public void onClick(View v) {
             // TODO Auto-generated method stub
             getip = ip.getText().toString().trim();
             getport = port.getText().toString().trim();
             if(getip=="" || getip==null || getip.equals("")){
                 Toast.makeText(IniActivity.this, "請輸入IP", Toast.LENGTH_SHORT).show();
                 ip.setFocusable(true);
             }else if(getport=="" || getport==null || getport.equals("")){
                 Toast.makeText(IniActivity.this, "請輸入端口", Toast.LENGTH_SHORT).show();
                 port.setFocusable(true);
             }else{
             //progressDialog = ProgressDialog.show(IniActivity.this, "", "請稍後...", true, false);
 //new Thread() {
 //@Override
 //public void run() {
                     try {
                         Socket s = new Socket();
                         isa = new InetSocketAddress(getip,Integer.parseInt(getport)); 
                         s.connect(isa,5000); 
                         //showDialog("連接成功",IniActivity.this);
                         try {
                             //生成ContentValues对象
                             ContentValues values = new ContentValues();
                             //想该对象当中插入键值对,其中键是列名,值是希望插入到这一列的值,值必须和数据库当中的数据类型一致
                             values.put("ip", getip);
                             values.put("port",getport);
                             db = SQLiteDatabase.openOrCreateDatabase(config.f, null); 
                             if(row==0){
                                 db.insert("config", null, values);
                             }else{
                                 db.update("config", values ,null,null);
                             }
                             Toast.makeText(IniActivity.this, "連接成功", Toast.LENGTH_SHORT);
                             s.close();
                             Intent intent = new Intent(IniActivity.this,IniuserActivity.class);
                             startActivity(intent);
                             IniActivity.this.finish();
                             db.close();
                         } catch (Exception e) {
                             // TODO: handle exception
                             showDialog("設置失敗,數據庫不可用",IniActivity.this);
                         }
                         
                         
                     } catch (UnknownHostException e) {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
                         showDialog("連接失敗,IP或者端口不可用",IniActivity.this);
                     }catch (SocketTimeoutException  e) {
                           System.out.println("連接超時,服務器未開啟或IP錯誤");
                           showDialog("連接超時,服務器未開啟或IP錯誤",IniActivity.this);
                           e.printStackTrace();
                     }
                     catch (IOException e) {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
                         showDialog("連接失敗,IP或者端口不可用",IniActivity.this);
                     }
                     //progressDialog.dismiss();
 //finish();
 //}
 //}.start();
             }
             
         }
         
     }
     
     /**
      * define a dialog for show the message
      * @param mess
      * @param activity
 */
     public void showDialog(String mess,Activity activity){
       new AlertDialog.Builder(activity).setTitle("信息")
        .setMessage(mess)
        .setNegativeButton("確定",new DialogInterface.OnClickListener()
        {
          public void onClick(DialogInterface dialog, int which)
          {          
          }
        })
        .show();
     }
 }

3.初始化用户名称Activity, IniuserActivity.java

public class IniuserActivity extends Activity{
     private EditText name;
     private Button ok;
     private SQLiteDatabase db;
     
     private String nameString;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         // TODO Auto-generated method stub
         super.onCreate(savedInstanceState);
         setContentView(R.layout.configuser);
         
         name = (EditText)findViewById(R.id.name);
         ok = (Button)findViewById(R.id.ok);
         ok.setOnClickListener(new okButtonListenner());
         
         
         db = SQLiteDatabase.openOrCreateDatabase(config.f, null);
         try {
             Cursor cursor = db.query("config", new String[]{"name"},null,null, null, null, null);
             while(cursor.moveToNext()){
                 nameString = cursor.getString(cursor.getColumnIndex("name"));
             }
             name.setText(nameString);
             cursor.close();
         } catch (Exception e) {
             // TODO: handle exception
             System.out.println(e.toString());
         }
         db.close();
     }
     
     class okButtonListenner implements OnClickListener{
 
         @Override
         public void onClick(View v) {
             // TODO Auto-generated method stub
             String getname = name.getText().toString().trim();
             if(getname==""){
                 Toast.makeText(IniuserActivity.this, "請輸入您的稱呢", Toast.LENGTH_SHORT).show();
                 name.setFocusable(true);
             }else{            
                 try {
                     //生成ContentValues对象
                     ContentValues values = new ContentValues();
                     //想该对象当中插入键值对,其中键是列名,值是希望插入到这一列的值,值必须和数据库当中的数据类型一致
                     values.put("name", getname);
                     db = SQLiteDatabase.openOrCreateDatabase(config.f, null); 
                     db.update("config",values,null,null);
                     Toast.makeText(IniuserActivity.this, "設置完成", Toast.LENGTH_SHORT).show();
                     Intent intent = new Intent(IniuserActivity.this,SocketmsgActivity.class);
                     startActivity(intent);
                     IniuserActivity.this.finish();
                     db.close();
                 } catch (Exception e) {
                     // TODO: handle exception
                     showDialog("設置失敗,數據庫不可用",IniuserActivity.this);
                 }
             }
         }
         
     }
     
     /**
      * define a dialog for show the message
      * @param mess
      * @param activity
 */
     public void showDialog(String mess,Activity activity){
       new AlertDialog.Builder(activity).setTitle("信息")
        .setMessage(mess)
        .setNegativeButton("確定",new DialogInterface.OnClickListener()
        {
          public void onClick(DialogInterface dialog, int which)
          {          
          }
        })
        .show();
     }
 }

4.config.java

public class config{
    public static String SDCARD = android.os.Environment.getExternalStorageDirectory().getAbsolutePath();
    public static File path = new File(SDCARD+"/RunChatDatabase/"); //数据库文件目录   
    public static File f = new File(SDCARD+"/RunChatDatabase/config.db"); //数据库文件  
}

布局文件:

1.main.xml

<?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical" android:layout_width="fill_parent"
     android:layout_height="fill_parent">
     <EditText android:id="@+id/chatbox" android:layout_width="fill_parent"
         android:layout_height="fill_parent" android:layout_weight="1">
     </EditText>
     <EditText android:id="@+id/chattxt" android:layout_width="fill_parent"
         android:layout_height="wrap_content" android:gravity="top"
         android:hint="你想和对方说点什么?">
     </EditText>
     <Button android:id="@+id/chatOk" android:layout_width="fill_parent"
         android:layout_height="wrap_content" android:text="Send" 
         android:textSize="@dimen/btn1">
     </Button>
 
 </LinearLayout>

2.config.xml

<?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical" android:layout_width="fill_parent"
     android:layout_height="fill_parent">
     <EditText android:id="@+id/chatbox" android:layout_width="fill_parent"
         android:layout_height="fill_parent" android:layout_weight="1">
     </EditText>
     <EditText android:id="@+id/chattxt" android:layout_width="fill_parent"
         android:layout_height="wrap_content" android:gravity="top"
         android:hint="你想和对方说点什么?">
     </EditText>
     <Button android:id="@+id/chatOk" android:layout_width="fill_parent"
         android:layout_height="wrap_content" android:text="Send" 
         android:textSize="@dimen/btn1">
     </Button>
 
 </LinearLayout>

3.configuer.xml

<?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical" android:layout_width="fill_parent"
     android:layout_height="fill_parent">
     <EditText android:id="@+id/chatbox" android:layout_width="fill_parent"
         android:layout_height="fill_parent" android:layout_weight="1">
     </EditText>
     <EditText android:id="@+id/chattxt" android:layout_width="fill_parent"
         android:layout_height="wrap_content" android:gravity="top"
         android:hint="你想和对方说点什么?">
     </EditText>
     <Button android:id="@+id/chatOk" android:layout_width="fill_parent"
         android:layout_height="wrap_content" android:text="Send" 
         android:textSize="@dimen/btn1">
     </Button>
 
 </LinearLayout>

style文件:dimens.xml

<?xml version="1.0" encoding="utf-8"?>
 <resources>     
     <dimen name="h3">30dip</dimen> 
     <dimen name="h2">40dip</dimen> 
     <dimen name="btn1">30dip</dimen>
     <dimen name="et1">25dip</dimen>
 </resources>

最后是服务器文件:Server.java

import java.io.*;
 import java.net.*;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.*;
 
 import javax.sound.sampled.Port;
 import javax.swing.JOptionPane;
 
 public class Server {
     
     ServerSocket ss = null;
     private String getnameString=null;
     boolean started = false;
     List<Client> clients = new ArrayList<Client>();
     List<Info> infos = new ArrayList<Info>();
     public static void main(String[] args) {
         String inputport = JOptionPane.showInputDialog("請輸入該服務器使用的端口:");
         int port = Integer.parseInt(inputport);
         new Server().start(port);
     }
  
     public void start(int port) {
         try {
            ss = new ServerSocket(port);
            System.out.println("服務器啟動");
            started = true;
         } catch (BindException e) {
               System.out.println(" 端口已经被占用");
               System.exit(0);
            }
           catch (IOException e) {
              e.printStackTrace();
           }
 
       try {
          while (started) {
              Socket s = ss.accept();
              Client c = new Client (s);
              System.out.println("a client is connected");
              new Thread(c).start();
              clients.add(c);
              
              
          }
       } catch (IOException e) {
             e.printStackTrace();
          }
          finally {
             try {
                ss.close();
             } catch (IOException e) {
                   e.printStackTrace();
                }
          }
    }
    public List<Client> getClient(){
        return clients;
    }
 
   class Client implements Runnable {
      private String chatKey="SLEEKNETGEOCK4stsjeS";
      private Socket s = null;
      private DataInputStream dis = null;
      private DataOutputStream dos = null;
      private boolean bConnected = false;
      private String sendmsg=null;
      Client (Socket s) {
         this.s = s;
         try {
           dis = new DataInputStream (s.getInputStream());
           dos = new DataOutputStream (s.getOutputStream());
           bConnected = true;
         } catch(IOException e) {
               e.printStackTrace();
            }
      }
      
      public void send (String str) {
          
          try {
              //System.out.println(s);
              dos.writeUTF(str+"");
              dos.flush();
          } catch(IOException e) {
              clients.remove(this);
              System.out.println("对方已经退出了");
          }
      }
      public void run() {
          try {
             while (bConnected) {
                 String str = dis.readUTF();
                 DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                 String date = "  ["+df.format(new Date())+"]";
                 if(str.startsWith(chatKey+"online:")){
                     Info info = new Info();
                     getnameString = str.substring(27);
                     
                     info.setName(getnameString);
                     infos.add(info);
                     for (int i=0; i<clients.size(); i++) {
                       Client c = clients.get(i);
                       c.send(getnameString+" on line."+date);
                     }
                     System.out.println(getnameString+" on line."+date);
                 }else if(str.startsWith(chatKey+"offline:")){
                     getnameString = str.substring(28);
                     clients.remove(this);
                     for (int i=0; i<clients.size(); i++) {
                           Client c = clients.get(i);
                           c.send(getnameString+" off line."+date);
                         }
                     System.out.println(getnameString+" off line."+date);
                 }
                 else{
                     int charend = str.indexOf("end;");
                     String chatString = str.substring(charend+4);
                     String chatName = str.substring(25, charend);
                     
                     sendmsg=chatName+date+"\n"+chatString; 
                     for (int i=0; i<clients.size(); i++) {
                         Client c = clients.get(i);
                         c.send(sendmsg);
                       }
                     System.out.println(sendmsg);
                 }
              }
          } catch (SocketException e) {
              System.out.println("client is closed!");
              clients.remove(this);
          } catch (EOFException e) {
                System.out.println("client is closed!");
                clients.remove(this);
             }
             catch (IOException e) {
                e.printStackTrace();
             }
            finally {
              try {
                if (dis != null) dis.close();
                if (dos != null) dos.close();
                if (s != null) s.close();
              } catch (IOException e) {
                    e.printStackTrace();
                }
            }
      }
   }
   
   class Info{
       private String info_name = null;
       public Info(){
           
       }
       public void setName(String name){
           info_name = name;
       }
       public String getName(){
           return info_name;
       }
   }
 }

以上只是一个粗略的聊天室功能,如果要实现私聊,还需要保存该Socket关联的客户信息。一个客户端可以将信息发送另一个指定客户端。实际上,我们知道所有客户端只与服务器连接,客户端之间并没有互相连接。这个功能等我以后有时间再写个demo.....

posted on 2012-02-05 17:23  plusx  阅读(2943)  评论(1编辑  收藏  举报

导航