在Java中我们可以利用socket编程实现聊天室,在Android中也一样,因为Android完全支持JDK本身的TCP、UDP网络通信API。我们可以使用ServerSocket、Socket来建立基于TCP/IP协议的网络通信;也可以使用DatagramSocket、Datagrampacket、MulticastSocket来建立基于UDP协议的网络通信。下面实现一个简单的聊天室,服务器端完全用Java代码实现,跟Android无关,客户端用Android应用来实现。

服务器不断读取来自客户端的信息,并即时地将信息发送给每个连接到本服务器上的客户端,每个客户端可以向服务器发送消息,并不断地接收来自服务器的消息,并将消息显示在界面上。这样就实现了客户端与客户端之间的即时聊天功能。代码如下:

服务器端:

创建服务器的主类:

[java] view plain copy
  1. packagecom.home.server;
  2. importjava.io.IOException;
  3. importjava.net.ServerSocket;
  4. importjava.net.Socket;
  5. importjava.util.ArrayList;
  6. publicclassMyServer{
  7. //定义保存所有Socket的集合
  8. publicstaticArrayList<Socket>socketList=newArrayList<Socket>();
  9. publicstaticvoidmain(String[]args)throwsIOException{
  10. ServerSocketss=newServerSocket(20000);
  11. System.out.println("服务器创建成功!");
  12. System.out.println("等待客戶端的连接。。。");
  13. while(true){
  14. //此行代码会阻塞,等待用户的连接
  15. Socketsocket=ss.accept();
  16. System.out.println("有客户端连接进来!");
  17. socketList.add(socket);
  18. //每当客户端连接后启动一条ServerThread线程为该客户端服务
  19. newThread(newServerThread(socket)).start();
  20. }
  21. }
  22. }

服务器的线程类:

[java] view plain copy
  1. packagecom.home.server;
  2. importjava.io.BufferedReader;
  3. importjava.io.IOException;
  4. importjava.io.InputStreamReader;
  5. importjava.io.OutputStream;
  6. importjava.net.Socket;
  7. publicclassServerThreadimplementsRunnable{
  8. //定义当前线程所处理的Socket
  9. privateSocketsocket=null;
  10. //该线程所处理的Socket所对应的输入流
  11. BufferedReaderbr=null;
  12. publicServerThread(Socketsocket)throwsIOException{
  13. this.socket=socket;
  14. //初始化该Socket对应的输入流
  15. br=newBufferedReader(newInputStreamReader(socket.getInputStream(),
  16. "utf-8"));
  17. }
  18. @Override
  19. publicvoidrun(){
  20. try{
  21. Stringcontent=null;
  22. //采用循环不断从Socket中读取客户端发送过来的数据
  23. while((content=readFromClient())!=null){
  24. //遍历socketList中的每个Socket,将读到的内容向每个Socket发送一次
  25. for(Sockets:MyServer.socketList){
  26. OutputStreamos=s.getOutputStream();
  27. os.write((content+"\n").getBytes("utf-8"));
  28. }
  29. }
  30. }catch(Exceptione){
  31. e.printStackTrace();
  32. }
  33. }
  34. /**
  35. *定义读取客户端数据的方法
  36. *
  37. *@return
  38. */
  39. privateStringreadFromClient(){
  40. try{
  41. returnbr.readLine();
  42. }
  43. //如果捕捉到异常,表明该Socket对应的客户端已经关闭
  44. catch(Exceptione){
  45. //删除该Socket
  46. MyServer.socketList.remove(socket);
  47. e.printStackTrace();
  48. }
  49. returnnull;
  50. }
  51. }

客户端主类(Activity):

[java] view plain copy
  1. packagecom.home.activity;
  2. importjava.io.OutputStream;
  3. importjava.net.Socket;
  4. importandroid.app.Activity;
  5. importandroid.os.Bundle;
  6. importandroid.os.Handler;
  7. importandroid.os.Message;
  8. importandroid.view.View;
  9. importandroid.view.View.OnClickListener;
  10. importandroid.widget.Button;
  11. importandroid.widget.EditText;
  12. importcom.home.R;
  13. importcom.home.util.ClientThread;
  14. publicclassMultiThreadClientextendsActivity{
  15. privateEditTextinput,show;
  16. privateButtonsendBtn;
  17. privateOutputStreamos;
  18. privateHandlerhandler;
  19. @Override
  20. protectedvoidonCreate(BundlesavedInstanceState){
  21. super.onCreate(savedInstanceState);
  22. setContentView(R.layout.activity_main);
  23. input=(EditText)findViewById(R.id.main_et_input);
  24. show=(EditText)findViewById(R.id.main_et_show);
  25. sendBtn=(Button)findViewById(R.id.main_btn_send);
  26. handler=newHandler(){
  27. @Override
  28. publicvoidhandleMessage(Messagemsg){
  29. //如果消息来自子线程
  30. if(msg.what==0x234){
  31. //将读取的内容追加显示在文本框中
  32. show.append("\n"+msg.obj.toString());
  33. }
  34. }
  35. };
  36. Socketsocket;
  37. try{
  38. socket=newSocket("192.168.0.101",20000);
  39. //客户端启动ClientThread线程不断读取来自服务器的数据
  40. newThread(newClientThread(socket,handler)).start();
  41. os=socket.getOutputStream();
  42. }catch(Exceptione){
  43. e.printStackTrace();
  44. }
  45. sendBtn.setOnClickListener(newOnClickListener(){
  46. @Override
  47. publicvoidonClick(Viewv){
  48. try{
  49. //将用户在文本框内输入的内容写入网络
  50. os.write((input.getText().toString()+"\r\n").getBytes());
  51. //清空input文本框数据
  52. input.setText("");
  53. }catch(Exceptione){
  54. e.printStackTrace();
  55. }
  56. }
  57. });
  58. }
  59. }

客户端线程类:

[java] view plain copy
  1. packagecom.home.util;
  2. importjava.io.BufferedReader;
  3. importjava.io.IOException;
  4. importjava.io.InputStreamReader;
  5. importjava.net.Socket;
  6. importandroid.os.Handler;
  7. importandroid.os.Message;
  8. publicclassClientThreadimplementsRunnable{
  9. privateHandlerhandler;
  10. //该线程所处理的Socket所对应的输入流
  11. privateBufferedReaderbr=null;
  12. publicClientThread(Socketsocket,Handlerhandler)throwsIOException{
  13. this.handler=handler;
  14. br=newBufferedReader(newInputStreamReader(socket.getInputStream()));
  15. }
  16. @Override
  17. publicvoidrun(){
  18. try{
  19. Stringcontent=null;
  20. //不断读取Socket输入流的内容
  21. while((content=br.readLine())!=null){
  22. //每当读到来自服务器的数据之后,发送消息通知程序界面显示该数据
  23. Messagemsg=newMessage();
  24. msg.what=0x234;
  25. msg.obj=content;
  26. handler.sendMessage(msg);
  27. }
  28. }catch(Exceptione){
  29. e.printStackTrace();
  30. }
  31. }
  32. }

Activity的布局XML:

[html] view plain copy
  1. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent"
  4. android:orientation="vertical">
  5. <LinearLayout
  6. android:layout_width="match_parent"
  7. android:layout_height="wrap_content"
  8. android:orientation="horizontal">
  9. <EditText
  10. android:id="@+id/main_et_input"
  11. android:layout_width="240dp"
  12. android:layout_height="wrap_content"/>
  13. <Button
  14. android:id="@+id/main_btn_send"
  15. android:layout_width="match_parent"
  16. android:layout_height="wrap_content"
  17. android:paddingLeft="10dp"
  18. android:text="发送"/>
  19. </LinearLayout>
  20. <EditText
  21. android:id="@+id/main_et_show"
  22. android:layout_width="match_parent"
  23. android:layout_height="match_parent"
  24. android:cursorVisible="false"
  25. android:editable="false"
  26. android:gravity="top"/>
  27. </LinearLayout>

权限:

[html] view plain copy
  1. <uses-permissionandroid:name="android.permission.INTERNET"/>

更多相关文章

  1. android异步任务完成后再执行主线程任务
  2. Android使用线程获取网络图片的方法
  3. android中使用多线程——HandlerThread举例
  4. android 多线程断点下载,listview 模式 开始 暂停等功能
  5. Android从服务器获取图片的实例方法
  6. Android客户端连接PC服务器端(Socket连接)
  7. android使用JSON进行网络数据交换(服务端、客户端)的实现
  8. Android文字转语音TTS离线程序
  9. Android下调用webservice的服务器端和客户端详解

随机推荐

  1. 通过UserAgent判断智能手机(设备,Android
  2. 13-7-5 android Tabhost功能实现
  3. Android直接播放麦克风采集到的声音
  4. android Q的init rc脚本创建目录失败问题
  5. Android 常用动画小结
  6. Android好轮子-封装很好的库
  7. Android(安卓)出现 avc: denied { execmo
  8. android 调试的一些小技巧
  9. Android NDK: No rule to make target
  10. Android 客户端选择响应最快的一个服务器