原文地址为: 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的请求,服务器端也对应产生一个SocketSocket s = ss.accept();//下面就可以使用Socket进行通信了...}

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

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

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

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

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

下面来看看整个功能的demo

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

   

服务器打印信息:

程序文件结构:

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

1.先看看主Activity : SocketmsgActivity.java

SocketmsgActivity.java

  1 public class SocketmsgActivity extends Activity {  2     /** Called when the activity is first created. */  3     private SQLiteDatabase db;  4       5     Thread thread = null;  6     Socket s = null;  7     private InetSocketAddress isa = null;   8   9     DataInputStream dis = null; 10     DataOutputStream dos = null; 11     private String reMsg=null; 12     private Boolean isContect = false; 13     private EditText chattxt; 14     private EditText chatbox; 15     private Button chatok; 16      17     private String chatKey="SLEEKNETGEOCK4stsjeS"; 18     private String name=null,ip=null,port=null; 19     @Override 20     public void onCreate(Bundle savedInstanceState) { 21         super.onCreate(savedInstanceState); 22         setContentView(R.layout.main); 23         chattxt = (EditText)findViewById(R.id.chattxt); 24         chatbox = (EditText)findViewById(R.id.chatbox); 25         chatok = (Button)findViewById(R.id.chatOk); 26         chatbox.setCursorVisible(false); 27         chatbox.setFocusable(false); 28         chatbox.setFocusableInTouchMode(false); 29         chatbox.setGravity(2); 30          31         //初始化,创建数据库来储存用户信息 32         InitDatabase(); 33         db = SQLiteDatabase.openOrCreateDatabase(config.f, null); 34         try { 35             Cursor cursor = db.query("config", new String[]{"ip","name","port"},null,null, null, null, null); 36             while(cursor.moveToNext()){ 37                 name = cursor.getString(cursor.getColumnIndex("name")); 38                 ip = cursor.getString(cursor.getColumnIndex("ip")); 39                 port = cursor.getString(cursor.getColumnIndex("port")); 40             } 41             cursor.close(); 42         } catch (Exception e) { 43             // TODO: handle exception 44             System.out.println(e.toString()); 45         } 46         db.close(); 47          48         //设置连接 49         if(ip==null || port==null){ 50             Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class); 51             startActivity(intent); 52             SocketmsgActivity.this.finish(); 53         } 54         //设置名称 55         else if(name==null){ 56             Intent intent = new Intent(SocketmsgActivity.this,IniuserActivity.class); 57             startActivity(intent); 58             SocketmsgActivity.this.finish(); 59         }else{ 60              61             connect(); 62             chatok.setOnClickListener(new View.OnClickListener() { 63      64                 @Override 65                 public void onClick(View v) { 66      67                     String str = chattxt.getText().toString().trim(); 68                     System.out.println(s); 69                     try { 70                         dos.writeUTF(chatKey+"name:"+name+"end;"+str); 71                         chattxt.setText(""); 72      73                     }catch (SocketTimeoutException  e) { 74                           System.out.println("連接超時,服務器未開啟或IP錯誤"); 75                           Toast.makeText(SocketmsgActivity.this, "連接超時,服務器未開啟或IP錯誤", Toast.LENGTH_SHORT).show(); 76                           Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class); 77                         startActivity(intent); 78                         SocketmsgActivity.this.finish(); 79                           e.printStackTrace(); 80                       } catch (IOException e) { 81                         // TODO Auto-generated catch block 82                           System.out.println("連接超時,服務器未開啟或IP錯誤"); 83                           Toast.makeText(SocketmsgActivity.this, "連接超時,服務器未開啟或IP錯誤", Toast.LENGTH_SHORT).show(); 84                           Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class); 85                         startActivity(intent); 86                         SocketmsgActivity.this.finish(); 87                           e.printStackTrace(); 88                     } 89                 } 90             }); 91         } 92     } 93      94     private Runnable doThread = new Runnable() { 95         public void run() { 96             System.out.println("running!"); 97             ReceiveMsg(); 98         } 99     };   100     101     public void connect() {102         try {103             s = new Socket();104             isa = new InetSocketAddress(ip,Integer.parseInt(port)); 105             s.connect(isa,5000); 106 107             if(s.isConnected()){108                 dos = new DataOutputStream (s.getOutputStream());109                 dis = new DataInputStream (s.getInputStream());110                 dos.writeUTF(chatKey+"online:"+name);111                 /**112                  * 这里是关键,我在此耗时8h+113                  * 原因是 子线程不能直接更新UI114                  * 为此,我们需要通过Handler物件,通知主线程Ui Thread来更新界面。115                  * 116 */117                 thread = new Thread(null, doThread, "Message");118                   thread.start();119                   System.out.println("connect");120                   isContect=true;121             }122           }catch (UnknownHostException e) {123               System.out.println("連接失敗");124             Toast.makeText(SocketmsgActivity.this, "連接失敗", Toast.LENGTH_SHORT).show();125             Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);126             startActivity(intent);127             SocketmsgActivity.this.finish();128               e.printStackTrace();129           }catch (SocketTimeoutException  e) {130               System.out.println("連接超時,服務器未開啟或IP錯誤");131               Toast.makeText(SocketmsgActivity.this, "連接超時,服務器未開啟或IP錯誤", Toast.LENGTH_SHORT).show();132             Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);133             startActivity(intent);134             SocketmsgActivity.this.finish();135               e.printStackTrace();136           }catch (IOException e) {137               System.out.println("連接失敗");138               e.printStackTrace();139           }140     }141    142     public void disConnect() {143         if(dos!=null){144         try {145             146                 dos.writeUTF(chatKey+"offline:"+name);147             148         } catch (IOException e1) {149             // TODO Auto-generated catch block150             e1.printStackTrace();151         }152         try {153             s.close();154         } catch (IOException e) {155               e.printStackTrace();156         }157         }158     }159   160     161     /**162      * 线程监视Server信息163 */164     private void ReceiveMsg() {165         if (isContect) {166             try {167                 while ((reMsg = dis.readUTF()) != null) {168                     System.out.println(reMsg);169                     if (reMsg != null) {170 171                         try {172                             Message msgMessage = new Message();173                             msgMessage.what = 0x1981;174                             handler.sendMessage(msgMessage);175                             Thread.sleep(100);176                         } catch (InterruptedException e) {177                             // TODO Auto-generated catch block178                             e.printStackTrace();179                         }180 181                     }182                 }183             } catch (SocketException e) {184                 // TODO: handle exception185                 System.out.println("exit!");186             } catch (IOException e) {187                 // TODO Auto-generated catch block188                 e.printStackTrace();189             }190 191         }192     }193   194     /**195      * 通过handler更新UI196 */197     Handler handler = new Handler() {198         public void handleMessage(Message msg) {199             switch (msg.what) {200             case 0x1981:201                 chatbox.setText(chatbox.getText() + reMsg + '\n');202                 chatbox.setSelection(chatbox.length());203                 break;204             }205         }206     };207     208     @Override209     protected void onDestroy() {210         // TODO Auto-generated method stub211         super.onDestroy();212         disConnect();213         //System.exit(0);214     }215     216     @Override217     public boolean onCreateOptionsMenu(Menu menu) {218         // TODO Auto-generated method stub219         menu.add(0, 1, 1, "初始化設置");220         menu.add(0, 2, 2, "退出");221         return super.onCreateOptionsMenu(menu);222     }223 224     @Override225     public boolean onOptionsItemSelected(MenuItem item) {226         // TODO Auto-generated method stub227         if(item.getItemId()==1){228             Intent intent = new Intent(SocketmsgActivity.this,IniActivity.class);229             startActivity(intent);230             SocketmsgActivity.this.finish();231         }else if(item.getItemId()==2){232             disConnect();233             SocketmsgActivity.this.finish();  234             android.os.Process.killProcess(android.os.Process.myPid());235             System.exit(0);236         }237         return super.onOptionsItemSelected(item);238     }239 240     public void InitDatabase(){241          242         if(!config.path.exists()){  243             config.path.mkdirs();    244             Log.i("LogDemo", "mkdir");  245         }   246         if(!config.f.exists()){      247             try{   248                 config.f.createNewFile();  249                 Log.i("LogDemo", "create a new database file");250             }catch(IOException e){   251                 Log.i("LogDemo",e.toString());252             }   253         }  254         try {255             if(tabIsExist("config")==false){256                 db = SQLiteDatabase.openOrCreateDatabase(config.f, null);  257                 db.execSQL("create table config(_id integer primary key autoincrement," +258                         "ip varchar(128),port varchar(10),name varchar(32))");259                 Log.i("LogDemo", "create a database");260                 db.close();261             }262         } catch (Exception e) {263             // TODO: handle exception264             Log.i("LogDemo",e.toString());265         }266     }267     268     /**269      * check the database is already exist270      * @param tabName271      * @return272 */273     public boolean tabIsExist(String tabName){274         boolean result = false;275         if(tabName == null){276                 return false;277         }278         Cursor cursor = null;279         db = SQLiteDatabase.openOrCreateDatabase(config.f, null); 280         try {281             String sql = "select count(*) as c from sqlite_master where type ='table' " +282                         "and name ='"+tabName.trim()+"' ";283             cursor = db.rawQuery(sql, null);284             if(cursor.moveToNext()){285                 int count = cursor.getInt(0);286                 if(count>0){287                     result = true;288                 }289             }290                 291         } catch (Exception e) {292                 // TODO: handle exception293         }  294         cursor.close();295         db.close();296         return result;297     }298 }

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

IniActivity.java

  1 public class IniActivity extends Activity{  2   3     private EditText ip,port;  4     private Button nextButton;  5     private String getip,getport;  6     private ProgressDialog progressDialog;  7     private InetSocketAddress isa = null;   8     private SQLiteDatabase db;  9     private String ipstring=null,portString=null; 10     private int row=0; 11     @Override 12     protected void onCreate(Bundle savedInstanceState) { 13         // TODO Auto-generated method stub 14         super.onCreate(savedInstanceState); 15         setContentView(R.layout.config); 16          17         ip = (EditText)findViewById(R.id.ip); 18         port = (EditText)findViewById(R.id.port); 19         nextButton = (Button)findViewById(R.id.next); 20          21          22         db = SQLiteDatabase.openOrCreateDatabase(config.f, null); 23         try { 24             Cursor cursor = db.query("config", new String[]{"ip","port"},null,null, null, null, null); 25             while(cursor.moveToNext()){ 26                 ipstring = cursor.getString(cursor.getColumnIndex("ip")); 27                 portString = cursor.getString(cursor.getColumnIndex("port")); 28                 row++; 29             } 30             ip.setText(ipstring); 31             port.setText(portString); 32             cursor.close(); 33         } catch (Exception e) { 34             // TODO: handle exception 35             System.out.println(e.toString()); 36         } 37         db.close(); 38          39         nextButton.setOnClickListener(new nextButtonListenner()); 40     } 41      42     class nextButtonListenner implements OnClickListener{ 43  44         @Override 45         public void onClick(View v) { 46             // TODO Auto-generated method stub 47             getip = ip.getText().toString().trim(); 48             getport = port.getText().toString().trim(); 49             if(getip=="" || getip==null || getip.equals("")){ 50                 Toast.makeText(IniActivity.this, "請輸入IP", Toast.LENGTH_SHORT).show(); 51                 ip.setFocusable(true); 52             }else if(getport=="" || getport==null || getport.equals("")){ 53                 Toast.makeText(IniActivity.this, "請輸入端口", Toast.LENGTH_SHORT).show(); 54                 port.setFocusable(true); 55             }else{ 56             //progressDialog = ProgressDialog.show(IniActivity.this, "", "請稍後...", true, false); 57 //new Thread() { 58 //@Override 59 //public void run() { 60                     try { 61                         Socket s = new Socket(); 62                         isa = new InetSocketAddress(getip,Integer.parseInt(getport));  63                         s.connect(isa,5000);  64                         //showDialog("連接成功",IniActivity.this); 65                         try { 66                             //生成ContentValues对象 67                             ContentValues values = new ContentValues(); 68                             //想该对象当中插入键值对,其中键是列名,值是希望插入到这一列的值,值必须和数据库当中的数据类型一致 69                             values.put("ip", getip); 70                             values.put("port",getport); 71                             db = SQLiteDatabase.openOrCreateDatabase(config.f, null);  72                             if(row==0){ 73                                 db.insert("config", null, values); 74                             }else{ 75                                 db.update("config", values ,null,null); 76                             } 77                             Toast.makeText(IniActivity.this, "連接成功", Toast.LENGTH_SHORT); 78                             s.close(); 79                             Intent intent = new Intent(IniActivity.this,IniuserActivity.class); 80                             startActivity(intent); 81                             IniActivity.this.finish(); 82                             db.close(); 83                         } catch (Exception e) { 84                             // TODO: handle exception 85                             showDialog("設置失敗,數據庫不可用",IniActivity.this); 86                         } 87                          88                          89                     } catch (UnknownHostException e) { 90                         // TODO Auto-generated catch block 91                         e.printStackTrace(); 92                         showDialog("連接失敗,IP或者端口不可用",IniActivity.this); 93                     }catch (SocketTimeoutException  e) { 94                           System.out.println("連接超時,服務器未開啟或IP錯誤"); 95                           showDialog("連接超時,服務器未開啟或IP錯誤",IniActivity.this); 96                           e.printStackTrace(); 97                     } 98                     catch (IOException e) { 99                         // TODO Auto-generated catch block100                         e.printStackTrace();101                         showDialog("連接失敗,IP或者端口不可用",IniActivity.this);102                     }103                     //progressDialog.dismiss();104 //finish();105 //}106 //}.start();107             }108             109         }110         111     }112     113     /**114      * define a dialog for show the message115      * @param mess116      * @param activity117 */118     public void showDialog(String mess,Activity activity){119       new AlertDialog.Builder(activity).setTitle("信息")120        .setMessage(mess)121        .setNegativeButton("確定",new DialogInterface.OnClickListener()122        {123          public void onClick(DialogInterface dialog, int which)124          {          125          }126        })127        .show();128     }129 }

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

IniuserActivity.java

 1 public class IniuserActivity extends Activity{ 2     private EditText name; 3     private Button ok; 4     private SQLiteDatabase db; 5      6     private String nameString; 7     @Override 8     protected void onCreate(Bundle savedInstanceState) { 9         // TODO Auto-generated method stub10         super.onCreate(savedInstanceState);11         setContentView(R.layout.configuser);12         13         name = (EditText)findViewById(R.id.name);14         ok = (Button)findViewById(R.id.ok);15         ok.setOnClickListener(new okButtonListenner());16         17         18         db = SQLiteDatabase.openOrCreateDatabase(config.f, null);19         try {20             Cursor cursor = db.query("config", new String[]{"name"},null,null, null, null, null);21             while(cursor.moveToNext()){22                 nameString = cursor.getString(cursor.getColumnIndex("name"));23             }24             name.setText(nameString);25             cursor.close();26         } catch (Exception e) {27             // TODO: handle exception28             System.out.println(e.toString());29         }30         db.close();31     }32     33     class okButtonListenner implements OnClickListener{34 35         @Override36         public void onClick(View v) {37             // TODO Auto-generated method stub38             String getname = name.getText().toString().trim();39             if(getname==""){40                 Toast.makeText(IniuserActivity.this, "請輸入您的稱呢", Toast.LENGTH_SHORT).show();41                 name.setFocusable(true);42             }else{            43                 try {44                     //生成ContentValues对象45                     ContentValues values = new ContentValues();46                     //想该对象当中插入键值对,其中键是列名,值是希望插入到这一列的值,值必须和数据库当中的数据类型一致47                     values.put("name", getname);48                     db = SQLiteDatabase.openOrCreateDatabase(config.f, null); 49                     db.update("config",values,null,null);50                     Toast.makeText(IniuserActivity.this, "設置完成", Toast.LENGTH_SHORT).show();51                     Intent intent = new Intent(IniuserActivity.this,SocketmsgActivity.class);52                     startActivity(intent);53                     IniuserActivity.this.finish();54                     db.close();55                 } catch (Exception e) {56                     // TODO: handle exception57                     showDialog("設置失敗,數據庫不可用",IniuserActivity.this);58                 }59             }60         }61         62     }63     64     /**65      * define a dialog for show the message66      * @param mess67      * @param activity68 */69     public void showDialog(String mess,Activity activity){70       new AlertDialog.Builder(activity).setTitle("信息")71        .setMessage(mess)72        .setNegativeButton("確定",new DialogInterface.OnClickListener()73        {74          public void onClick(DialogInterface dialog, int which)75          {          76          }77        })78        .show();79     }80 }

4.config.java

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

main.xml

 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3     android:orientation="vertical" android:layout_width="fill_parent" 4     android:layout_height="fill_parent"> 5     <EditText android:id="@+id/chatbox" android:layout_width="fill_parent" 6         android:layout_height="fill_parent" android:layout_weight="1"> 7     </EditText> 8     <EditText android:id="@+id/chattxt" android:layout_width="fill_parent" 9         android:layout_height="wrap_content" android:gravity="top"10         android:hint="你想和对方说点什么?">11     </EditText>12     <Button android:id="@+id/chatOk" android:layout_width="fill_parent"13         android:layout_height="wrap_content" android:text="Send" 14         android:textSize="@dimen/btn1">15     </Button>16 17 </LinearLayout>

2.config.xml

config.xml

 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4   android:orientation="vertical" 5   android:layout_width="match_parent" 6   android:layout_height="match_parent"> 7     <TextView  8 android:layout_width="fill_parent" 9         android:layout_height="wrap_content"10         android:text="初始化設置"11         android:textSize="@dimen/h2"/>12     <TextView 13 android:layout_width="fill_parent"14         android:layout_height="wrap_content"15         android:text="服務器IP"16         android:textSize="@dimen/h3"/>17     <EditText 18 android:layout_width="fill_parent"19         android:layout_height="wrap_content"20         android:hint="192.168.2.214"21         android:id="@+id/ip"22         android:textSize="@dimen/et1"/>23         24     <TextView 25 android:layout_width="fill_parent"26         android:layout_height="wrap_content"27         android:text="端口"28         android:textSize="@dimen/h3"/>29     <EditText 30 android:layout_width="fill_parent"31         android:layout_height="wrap_content"32         android:hint="8888"33         android:id="@+id/port"34         android:textSize="@dimen/et1"/>35         36     <Button 37 android:layout_width="fill_parent"38         android:layout_height="wrap_content"39         android:text="下一步"40         android:id="@+id/next"41         android:textSize="@dimen/btn1"/>        42 </LinearLayout>

3.configuer.xml

configuser.xml

 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4   android:orientation="vertical" 5   android:layout_width="match_parent" 6   android:layout_height="match_parent"> 7     <TextView  8 android:layout_width="fill_parent" 9         android:layout_height="wrap_content"10         android:text="初始化設置"11         android:textSize="@dimen/h2"/>12     <TextView 13 android:layout_width="fill_parent"14         android:layout_height="wrap_content"15         android:text="您的稱呢"16         android:textSize="@dimen/h3"/>17     <EditText 18 android:layout_width="fill_parent"19         android:layout_height="wrap_content"20         android:hint="潤仔"21         android:id="@+id/name"22         android:maxLength="20"23         android:textSize="@dimen/et1"/>24         25     <Button 26 android:layout_width="fill_parent"27         android:layout_height="wrap_content"28         android:text="完成"29         android:id="@+id/ok"30         android:textSize="@dimen/btn1"/>    31 </LinearLayout>

style文件:dimens.xml

dimens.xml

1 <?xml version="1.0" encoding="utf-8"?>2 <resources>     3     <dimen name="h3">30dip</dimen> 4     <dimen name="h2">40dip</dimen> 5     <dimen name="btn1">30dip</dimen>6     <dimen name="et1">25dip</dimen>7 </resources> 

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

  1 import java.io.*;  2 import java.net.*;  3 import java.text.DateFormat;  4 import java.text.SimpleDateFormat;  5 import java.util.*;  6   7 import javax.sound.sampled.Port;  8 import javax.swing.JOptionPane;  9  10 public class Server { 11      12     ServerSocket ss = null; 13     private String getnameString=null; 14     boolean started = false; 15     List<Client> clients = new ArrayList<Client>(); 16     List<Info> infos = new ArrayList<Info>(); 17     public static void main(String[] args) { 18         String inputport = JOptionPane.showInputDialog("請輸入該服務器使用的端口:"); 19         int port = Integer.parseInt(inputport); 20         new Server().start(port); 21     } 22   23     public void start(int port) { 24         try { 25            ss = new ServerSocket(port); 26            System.out.println("服務器啟動"); 27            started = true; 28         } catch (BindException e) { 29               System.out.println(" 端口已经被占用"); 30               System.exit(0); 31            } 32           catch (IOException e) { 33              e.printStackTrace(); 34           } 35  36       try { 37          while (started) { 38              Socket s = ss.accept(); 39              Client c = new Client (s); 40              System.out.println("a client is connected"); 41              new Thread(c).start(); 42              clients.add(c); 43               44               45          } 46       } catch (IOException e) { 47             e.printStackTrace(); 48          } 49          finally { 50             try { 51                ss.close(); 52             } catch (IOException e) { 53                   e.printStackTrace(); 54                } 55          } 56    } 57    public List<Client> getClient(){ 58        return clients; 59    } 60  61   class Client implements Runnable { 62      private String chatKey="SLEEKNETGEOCK4stsjeS"; 63      private Socket s = null; 64      private DataInputStream dis = null; 65      private DataOutputStream dos = null; 66      private boolean bConnected = false; 67      private String sendmsg=null; 68      Client (Socket s) { 69         this.s = s; 70         try { 71           dis = new DataInputStream (s.getInputStream()); 72           dos = new DataOutputStream (s.getOutputStream()); 73           bConnected = true; 74         } catch(IOException e) { 75               e.printStackTrace(); 76            } 77      } 78       79      public void send (String str) { 80           81          try { 82              //System.out.println(s); 83              dos.writeUTF(str+""); 84              dos.flush(); 85          } catch(IOException e) { 86              clients.remove(this); 87              System.out.println("对方已经退出了"); 88          } 89      } 90      public void run() { 91          try { 92             while (bConnected) { 93                 String str = dis.readUTF(); 94                 DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); 95                 String date = "  ["+df.format(new Date())+"]"; 96                 if(str.startsWith(chatKey+"online:")){ 97                     Info info = new Info(); 98                     getnameString = str.substring(27); 99                     100                     info.setName(getnameString);101                     infos.add(info);102                     for (int i=0; i<clients.size(); i++) {103                       Client c = clients.get(i);104                       c.send(getnameString+" on line."+date);105                     }106                     System.out.println(getnameString+" on line."+date);107                 }else if(str.startsWith(chatKey+"offline:")){108                     getnameString = str.substring(28);109                     clients.remove(this);110                     for (int i=0; i<clients.size(); i++) {111                           Client c = clients.get(i);112                           c.send(getnameString+" off line."+date);113                         }114                     System.out.println(getnameString+" off line."+date);115                 }116                 else{117                     int charend = str.indexOf("end;");118                     String chatString = str.substring(charend+4);119                     String chatName = str.substring(25, charend);120                     121                     sendmsg=chatName+date+"\n"+chatString; 122                     for (int i=0; i<clients.size(); i++) {123                         Client c = clients.get(i);124                         c.send(sendmsg);125                       }126                     System.out.println(sendmsg);127                 }128              }129          } catch (SocketException e) {130              System.out.println("client is closed!");131              clients.remove(this);132          } catch (EOFException e) {133                System.out.println("client is closed!");134                clients.remove(this);135             }136             catch (IOException e) {137                e.printStackTrace();138             }139            finally {140              try {141                if (dis != null) dis.close();142                if (dos != null) dos.close();143                if (s != null) s.close();144              } catch (IOException e) {145                    e.printStackTrace();146                }147            }148      }149   }150   151   class Info{152       private String info_name = null;153       public Info(){154           155       }156       public void setName(String name){157           info_name = name;158       }159       public String getName(){160           return info_name;161       }162   }163 }

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

转载请注明本文地址: Android 基于Socket的聊天室

Android 基于Socket的聊天室相关推荐

  1. 【python】基于Socket的聊天室Python开发

    基于Socket的聊天室Python开发 一.Socket简述 二.创建服务端Server 2.1 创建服务端初始化 2.2 监听客户端连接 2.3 处理客户端消息 三.创建客户端Client 3.1 ...

  2. 基于socket的聊天室实现原理

    基于socket的聊天室,目前还比较少见,国内比较知名的有网易和碧海银沙聊天室.这种聊天室的特点很明显,不象CGI聊天室那样不管有没有人发言,都会定时刷新.而是当有人发言时,屏幕上才会出现新聊天内容, ...

  3. Python语言基于Socket实现聊天室(包含登录、注册功能)

    一.聊天室的整体架构 1.twisted:实现服务端,以及事件驱动 Twisted是用Python实现的基于事件驱动的网络引擎框架. 2.socket:实现客户端,以及事件驱动 3.tkinter:实 ...

  4. 【java毕业设计】基于java+原生Sevlet+socket的聊天室系统设计与实现(毕业论文+程序源码)——聊天室系统

    基于java+原生Sevlet+socket的聊天室系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+原生Sevlet+socket的聊天室系统设计与实现,文章末尾附有本毕业设 ...

  5. 基于WebSocket实现聊天室(Node)

    基于WebSocket实现聊天室(Node) WebSocket是基于TCP的长连接通信协议,服务端可以主动向前端传递数据,相比比AJAX轮询服务器,WebSocket采用监听的方式,减轻了服务器压力 ...

  6. Socket.IO聊天室~简单实用

    小编心语:大家过完圣诞准备迎元旦吧~小编在这里预祝大家元旦快乐!!这一次要分享的东西小编也不是很懂啊,总之小编把它拿出来是觉地比较稀奇,而且程序也没有那么难,是一个比较简单的程序,大家可以多多试试~ ...

  7. SpringBoot + Vue 实现基于 WebSocket 的聊天室(单聊)

    前言 在前一篇文章SpringBoot 集成 STOMP 实现一对一聊天的两种方法中简单介绍了如何利用 STOMP 实现单聊,本文则将以一个比较完整的示例展示实际应用,不过本文并未使用 STOMP,而 ...

  8. 基于Python的聊天室

    基于Python的聊天室 文章目录 基于Python的聊天室 一.引言 1.1 背景和意义 1.2 系统要实现的功能 1.2.1 用户登录 1.2.2 群发消息 1.2.3 一对一聊天 1.2.4 发 ...

  9. 基于linux网络聊天室的设计,参考基于linux网络聊天室的设计.doc

    参考基于linux网络聊天室的设计 长沙理工大学<高级操作系统>课程设计报告学 院 计算机与通信工程 专 业 计算机科学与技术 班 级 学 号 学生姓名 指导教师 课程成绩 完成日期 课程 ...

最新文章

  1. Android逆向--如何调试smali代码?
  2. python最佳实践指南试题_Python最佳实践指南 阅读笔记
  3. 2020年高等数学方法与提高(上海理工大学)学习笔记:无穷级数
  4. JS —— 存取器属性get()和set()
  5. 《数据库SQL实战》统计出当前各个title类型对应的员工当前薪水对应的平均工资。
  6. 银行加息前存的定期会随着加息吗?
  7. Vmware 安装虚拟工具 (二)
  8. 无序列表圆点变空心_前端HTML -- 列表标签
  9. MFC开发IM-第六篇、MFC 文本框 用法
  10. 【zoj2314】Reactor Cooling 有上下界可行流
  11. 使用Highcharts实现柱状图展示
  12. Spark1.0新特性--Spark SQL
  13. FFmpeg wav转pcm(十一)
  14. 八种常规常用的SQL查询语句
  15. numpy.asarray()函数
  16. 大数据查询与处理Pig培训:大数据查询处理技术解析
  17. rabbit 消息丢失
  18. Report ZD600PSR028_1
  19. 前端JS常用工具方法 , 收藏
  20. we-color-picker 微信小程序拾色器(颜色选择器)组件

热门文章

  1. base64图片转file的处理
  2. 利用python自动完成网页计算TEC等参数
  3. 计算机组成原理——TEC-2储存器实验
  4. DGUS组态软件中位变量图标怎么用
  5. cad2014卡顿的解决方法_cad2014画直线卡顿怎么回事
  6. Vue启动本地(.exe)文件
  7. 5G NR LDPC码(1)—— LDPC码设计原理
  8. colorkey口红怎么样_colorkey口红推荐什么颜色
  9. java协议标准与规范
  10. mybatis-plus快速入门,手把手搭建mybatis-plus第一个项目