【轉】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.....


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM