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的请求,服务器端也对应产生一个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
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
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
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
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
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
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
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
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的聊天室相关推荐
- 【python】基于Socket的聊天室Python开发
基于Socket的聊天室Python开发 一.Socket简述 二.创建服务端Server 2.1 创建服务端初始化 2.2 监听客户端连接 2.3 处理客户端消息 三.创建客户端Client 3.1 ...
- 基于socket的聊天室实现原理
基于socket的聊天室,目前还比较少见,国内比较知名的有网易和碧海银沙聊天室.这种聊天室的特点很明显,不象CGI聊天室那样不管有没有人发言,都会定时刷新.而是当有人发言时,屏幕上才会出现新聊天内容, ...
- Python语言基于Socket实现聊天室(包含登录、注册功能)
一.聊天室的整体架构 1.twisted:实现服务端,以及事件驱动 Twisted是用Python实现的基于事件驱动的网络引擎框架. 2.socket:实现客户端,以及事件驱动 3.tkinter:实 ...
- 【java毕业设计】基于java+原生Sevlet+socket的聊天室系统设计与实现(毕业论文+程序源码)——聊天室系统
基于java+原生Sevlet+socket的聊天室系统设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+原生Sevlet+socket的聊天室系统设计与实现,文章末尾附有本毕业设 ...
- 基于WebSocket实现聊天室(Node)
基于WebSocket实现聊天室(Node) WebSocket是基于TCP的长连接通信协议,服务端可以主动向前端传递数据,相比比AJAX轮询服务器,WebSocket采用监听的方式,减轻了服务器压力 ...
- Socket.IO聊天室~简单实用
小编心语:大家过完圣诞准备迎元旦吧~小编在这里预祝大家元旦快乐!!这一次要分享的东西小编也不是很懂啊,总之小编把它拿出来是觉地比较稀奇,而且程序也没有那么难,是一个比较简单的程序,大家可以多多试试~ ...
- SpringBoot + Vue 实现基于 WebSocket 的聊天室(单聊)
前言 在前一篇文章SpringBoot 集成 STOMP 实现一对一聊天的两种方法中简单介绍了如何利用 STOMP 实现单聊,本文则将以一个比较完整的示例展示实际应用,不过本文并未使用 STOMP,而 ...
- 基于Python的聊天室
基于Python的聊天室 文章目录 基于Python的聊天室 一.引言 1.1 背景和意义 1.2 系统要实现的功能 1.2.1 用户登录 1.2.2 群发消息 1.2.3 一对一聊天 1.2.4 发 ...
- 基于linux网络聊天室的设计,参考基于linux网络聊天室的设计.doc
参考基于linux网络聊天室的设计 长沙理工大学<高级操作系统>课程设计报告学 院 计算机与通信工程 专 业 计算机科学与技术 班 级 学 号 学生姓名 指导教师 课程成绩 完成日期 课程 ...
最新文章
- Android逆向--如何调试smali代码?
- python最佳实践指南试题_Python最佳实践指南 阅读笔记
- 2020年高等数学方法与提高(上海理工大学)学习笔记:无穷级数
- JS —— 存取器属性get()和set()
- 《数据库SQL实战》统计出当前各个title类型对应的员工当前薪水对应的平均工资。
- 银行加息前存的定期会随着加息吗?
- Vmware 安装虚拟工具 (二)
- 无序列表圆点变空心_前端HTML -- 列表标签
- MFC开发IM-第六篇、MFC 文本框 用法
- 【zoj2314】Reactor Cooling 有上下界可行流
- 使用Highcharts实现柱状图展示
- Spark1.0新特性--Spark SQL
- FFmpeg wav转pcm(十一)
- 八种常规常用的SQL查询语句
- numpy.asarray()函数
- 大数据查询与处理Pig培训:大数据查询处理技术解析
- rabbit 消息丢失
- Report ZD600PSR028_1
- 前端JS常用工具方法 , 收藏
- we-color-picker 微信小程序拾色器(颜色选择器)组件