Android 基于Socket的聊天室

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运行起来,然后再运行手机模拟器

 

   

服务器打印信息:

 

程序文件结构:


嘿嘿,大家别笑我,我的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                  * 原因是 子线程不能直接更新UI
114                  * 为此,我们需要通过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 block
150             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 block
178                             e.printStackTrace();
179                         }
180 
181                     }
182                 }
183             } catch (SocketException e) {
184                 // TODO: handle exception
185                 System.out.println("exit!");
186             } catch (IOException e) {
187                 // TODO Auto-generated catch block
188                 e.printStackTrace();
189             }
190 
191         }
192     }
193   
194     /**
195      * 通过handler更新UI
196 */
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     @Override
209     protected void onDestroy() {
210         // TODO Auto-generated method stub
211         super.onDestroy();
212         disConnect();
213         //System.exit(0);
214     }
215     
216     @Override
217     public boolean onCreateOptionsMenu(Menu menu) {
218         // TODO Auto-generated method stub
219         menu.add(0, 1, 1, "初始化設置");
220         menu.add(0, 2, 2, "退出");
221         return super.onCreateOptionsMenu(menu);
222     }
223 
224     @Override
225     public boolean onOptionsItemSelected(MenuItem item) {
226         // TODO Auto-generated method stub
227         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 exception
264             Log.i("LogDemo",e.toString());
265         }
266     }
267     
268     /**
269      * check the database is already exist
270      * @param tabName
271      * @return
272 */
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 exception
293         }  
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 block
100                         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 message
115      * @param mess
116      * @param activity
117 */
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 stub
10         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 exception
28             System.out.println(e.toString());
29         }
30         db.close();
31     }
32     
33     class okButtonListenner implements OnClickListener{
34 
35         @Override
36         public void onClick(View v) {
37             // TODO Auto-generated method stub
38             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 exception
57                     showDialog("設置失敗,數據庫不可用",IniuserActivity.this);
58                 }
59             }
60         }
61         
62     }
63     
64     /**
65      * define a dialog for show the message
66      * @param mess
67      * @param activity
68 */
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.....

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android JSP Socket 聊天室是一种基于Android平台和JSP服务器的实时聊天应用程序。Android作为客户端,通过Socket与JSP服务器建立连接,实现用户之间的实时聊天。以下是关于如何实现该聊天室的方法: 1. 客户端开发:首先,在Android应用中建立Socket连接。使用Socket类可以实现与服务器的通信。通过建立输入流和输出流,可以实现信息的发送和接收。在聊天室中,你可以为每个用户分配一个唯一的Socket连接来进行通信。 2. 服务器端开发:在JSP服务器中,通过接收客户端的Socket连接来进行通信。服务器可以创建一个线程池用于接收客户端的连接请求,并对每个连接进行处理,以便实现多用户的实时聊天功能。 3. 实现实时聊天:在聊天室中,当一个用户发送消息时,通过Socket将消息发送到服务器,服务器再将消息广播给其他在线用户,实现实时聊天。在这个过程中,可以使用线程来处理客户端和服务器的连接,以及消息的发送和接收。 4. 用户控制:在聊天室中,你还可以实现一些用户控制功能,如用户注册、登录、退出等。可以在用户加入聊天室时记录用户信息,并在用户退出时清除相关信息。 综上所述,Android JSP Socket 聊天室是一种基于Android平台和JSP服务器的实时聊天应用程序。通过Socket连接,用户可以实现实时聊天,并且可以实现一些用户控制功能。这种聊天室可以用于不同的场景,如在线交流、团队协作等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值