12、android socket使用demo:网络聊天
目录:
一、效果图
二、原代码分享
三、代码分析
四、总结
一、效果图如下:
客户端1: 客户端2:
二、原代码分享如下:
1、java代码只有一个
MainActivity.java
1 package com; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.io.OutputStream; 7 import java.io.UnsupportedEncodingException; 8 import java.net.ServerSocket; 9 import java.net.Socket; 10 import java.util.ArrayList; 11 12 import android.app.Activity; 13 import android.os.Bundle; 14 import android.os.Handler; 15 import android.os.Message; 16 import android.view.View; 17 import android.view.View.OnClickListener; 18 import android.widget.Button; 19 import android.widget.CheckBox; 20 import android.widget.CompoundButton; 21 import android.widget.CompoundButton.OnCheckedChangeListener; 22 import android.widget.EditText; 23 import android.widget.TextView; 24 25 import com.example.androidsockettest.R; 26 27 public class MainActivity extends Activity{ 28 29 private Button button_send = null; 30 private EditText et_ip = null; 31 private EditText et_port = null; 32 private EditText et_conent = null; 33 private TextView tv_history = null; 34 private CheckBox checkBoxSwitch = null; 35 private static int defaultPort = 8888; 36 public static ArrayList<Socket> socketList=new ArrayList<Socket>(); 37 38 private OutputStream out=null; 39 private Handler handler = null; 40 private Socket s = null; 41 String tag = "chatRoom"; 42 private BufferedReader buRead = null; 43 44 private final int UPDATE_HISTORY_CONTENT = 0; 45 private final int UPDATE_INPUT_CONTENT = 1; 46 47 @Override 48 protected void onCreate(Bundle savedInstanceState) { 49 // TODO Auto-generated method stub 50 super.onCreate(savedInstanceState); 51 setContentView(R.layout.main_activity); 52 53 init(); 54 55 configure(); 56 57 serverStart(); 58 } 59 60 @Override 61 protected void onDestroy() { 62 // TODO Auto-generated method stub 63 super.onDestroy(); 64 } 65 66 67 public void init() 68 { 69 button_send = (Button)findViewById(R.id.button_send); 70 et_ip = (EditText)findViewById(R.id.editText_ip); 71 et_port = (EditText)findViewById(R.id.EditText_port); 72 et_conent = (EditText)findViewById(R.id.EditText_content); 73 tv_history = (TextView)findViewById(R.id.textView_history_content); 74 checkBoxSwitch = (CheckBox)findViewById(R.id.checkBox_server_start); 75 } 76 77 78 public void configure() 79 { 80 button_send.setOnClickListener(new OnClickListener() { 81 82 @Override 83 public void onClick(View v) { 84 // TODO Auto-generated method stub 85 try { 86 String content = et_conent.getText().toString();//读取用户输入文本 87 88 if(out == null) 89 { 90 CommonUtils.LogWuwei(tag,"the fucking out is null"); 91 return; 92 } 93 94 out.write((content+"\n").getBytes("utf-8"));//写入socket 95 96 String history_content = tv_history.getText().toString(); 97 history_content+="你说:"+et_conent.getText()+"\n"; 98 99 100 Message msg = new Message(); 101 msg.what = UPDATE_HISTORY_CONTENT; 102 msg.obj = history_content; 103 handler.sendMessage(msg); 104 105 msg = new Message(); 106 msg.what = UPDATE_INPUT_CONTENT; 107 msg.obj = ""; 108 handler.sendMessage(msg); 109 110 111 CommonUtils.LogWuwei(tag, "send success"); 112 } catch (UnsupportedEncodingException e) { 113 // TODO Auto-generated catch block 114 e.printStackTrace(); 115 CommonUtils.LogWuwei(tag, "send failed "+e.getMessage()); 116 } catch (IOException e) { 117 // TODO Auto-generated catch block 118 e.printStackTrace(); 119 CommonUtils.LogWuwei(tag, "send failed "+e.getMessage()); 120 } 121 } 122 }); 123 124 125 checkBoxSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() { 126 127 @Override 128 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 129 // TODO Auto-generated method stub 130 if(isChecked) 131 { 132 CommonUtils.LogWuwei(tag, "clientStart"); 133 clientStart(); 134 } 135 else 136 { 137 CommonUtils.LogWuwei(tag, "clientStop"); 138 clientStop(); 139 } 140 } 141 }); 142 143 144 handler = new Handler() 145 { 146 @Override 147 public void handleMessage(Message msg) { 148 // TODO Auto-generated method stub 149 super.handleMessage(msg); 150 switch (msg.what) 151 { 152 case UPDATE_HISTORY_CONTENT: 153 CommonUtils.LogWuwei(tag, "更新历史记录"+msg.obj); 154 tv_history.setText((String)msg.obj); 155 break; 156 157 case UPDATE_INPUT_CONTENT: 158 CommonUtils.LogWuwei(tag, "清空输入记录"); 159 et_conent.setText("");//清空文本 160 break; 161 } 162 } 163 }; 164 165 } 166 167 168 public void serverStart() 169 { 170 try { 171 172 final ServerSocket ss = new ServerSocket(defaultPort); 173 174 CommonUtils.LogWuwei(tag, "on serverStart"); 175 176 new Thread() 177 { 178 public void run() 179 { 180 while(true) 181 { 182 try { 183 CommonUtils.LogWuwei(tag, "on serverStart: ready to accept"); 184 s=ss.accept(); 185 socketList.add(s); 186 buRead = new BufferedReader(new InputStreamReader(s.getInputStream(), "utf-8")); 187 188 String receive_content = null; 189 while ((receive_content=readFromClient())!=null) { 190 CommonUtils.LogWuwei(tag,"客户端说:"+receive_content); 191 192 String history_content = tv_history.getText().toString(); 193 history_content+=s.getInetAddress()+"说:"+receive_content+"\n"; 194 195 Message msg = new Message(); 196 msg.what = UPDATE_HISTORY_CONTENT; 197 msg.obj = history_content; 198 handler.sendMessage(msg); 199 200 201 for (Socket ss:socketList) 202 { 203 OutputStream out=ss.getOutputStream(); 204 out.write(("[服务器已经收到消息]"+"\n").getBytes("utf-8")); 205 } 206 } 207 208 209 } catch (UnsupportedEncodingException e) { 210 // TODO Auto-generated catch block 211 e.printStackTrace(); 212 } catch (IOException e) { 213 // TODO Auto-generated catch block 214 e.printStackTrace(); 215 } 216 217 } 218 } 219 }.start(); 220 221 } catch (IOException e) { 222 // TODO Auto-generated catch block 223 e.printStackTrace(); 224 } 225 226 } 227 228 229 private String readFromClient(){ 230 try { 231 return buRead.readLine(); 232 } catch (Exception e) { 233 //删除此Socket 234 socketList.remove(s); 235 } 236 return null; 237 } 238 239 240 public void clientStart() 241 { 242 new Thread(new Runnable() { 243 244 @Override 245 public void run() { 246 try { 247 String ip = et_ip.getText().toString(); 248 String port = et_port.getText().toString(); 249 250 if(!port.equals("") && port != null) 251 { 252 s=new Socket(ip, defaultPort); 253 } 254 else 255 { 256 s=new Socket(ip, Integer.parseInt(port)); 257 } 258 259 out=s.getOutputStream(); 260 CommonUtils.LogWuwei(tag, "clientStart success"); 261 262 } catch (IOException e) { 263 e.printStackTrace(); 264 CommonUtils.LogWuwei(tag, "clientStart failed "+e.getMessage()); 265 } 266 } 267 }).start(); 268 269 270 } 271 272 273 public void clientStop() 274 { 275 try { 276 if(s != null) 277 s.close(); 278 if(out != null) 279 out.close(); 280 281 } catch (IOException e) { 282 // TODO Auto-generated catch block 283 e.printStackTrace(); 284 } 285 286 287 } 288 289 }
2、xml文件也是只有一个
main_activity.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" > 5 6 <EditText 7 android:id="@+id/editText_ip" 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 android:layout_toRightOf="@+id/TextView_ip_tips" 11 android:layout_marginRight="15dp" 12 android:text="192.168.1.232" 13 android:ems="10"/> 14 15 <TextView 16 android:id="@+id/TextView_ip_tips" 17 android:layout_width="wrap_content" 18 android:layout_height="wrap_content" 19 android:layout_alignParentLeft="true" 20 android:layout_marginTop="16dp" 21 android:text="接受IP:" /> 22 23 <EditText 24 android:id="@+id/EditText_port" 25 android:layout_width="wrap_content" 26 android:layout_height="wrap_content" 27 android:layout_toRightOf="@+id/textView_port_tips" 28 android:layout_below="@+id/editText_ip" 29 android:layout_marginTop="16dp" 30 android:ems="10" 31 android:text="8888" 32 android:inputType="number" > 33 34 <requestFocus /> 35 </EditText> 36 37 <TextView 38 android:id="@+id/textView_port_tips" 39 android:layout_width="wrap_content" 40 android:layout_height="wrap_content" 41 android:layout_alignBottom="@+id/EditText_port" 42 android:layout_alignParentLeft="true" 43 android:text="输入端口号:" /> 44 45 <TextView 46 android:id="@+id/textView_history_content" 47 android:layout_width="match_parent" 48 android:layout_height="350dp" 49 android:layout_below="@+id/checkBox_server_start" /> 50 51 52 53 <Button 54 android:id="@+id/button_send" 55 android:layout_width="wrap_content" 56 android:layout_height="wrap_content" 57 android:layout_toRightOf="@+id/EditText_content" 58 android:layout_alignParentBottom="true" 59 android:text="发送" /> 60 61 <EditText 62 android:id="@+id/EditText_content" 63 android:layout_width="wrap_content" 64 android:layout_height="wrap_content" 65 android:layout_alignParentLeft="true" 66 android:layout_alignParentBottom="true" 67 android:ems="10" /> 68 69 <CheckBox 70 android:id="@+id/checkBox_server_start" 71 android:layout_width="wrap_content" 72 android:layout_height="wrap_content" 73 android:layout_alignParentLeft="true" 74 android:layout_below="@+id/EditText_port" 75 android:layout_marginLeft="24dp" 76 android:checked="false" 77 android:text="开启发送模式" /> 78 79 </RelativeLayout>
三、代码分析
流程分析:
1、服务端
程序开启的时候,执行serverStart()方法,将自身做为serverSocket,端口号为8888,做为socket的服务器跑起来;
在循环中,通过带有阻塞特性的accept函数等待连接,如果有连接,通过accept函数得到套接字s,然后通过s的getInputStream()方法得到输入流(也就是对方发送的内容),同事也从s的getInetAddress方法得到对方的ip地址;这样一来就读到了两个重要信息 ① ip地址 ②发送过来的内容
2、客户端
在通过设置edittext内容,配置得到对方的IP地址和端口号,如果选中"开启发送模式",然后创建套件字s,通过套接字的getOutputStream()方法得到可写流out;
“发送”按钮的回调函数是用来通过可写流-写入-套接字(写入内容为用户输入的文本)
这样一来,程序基本ok了,然后运行在两部手机上,即可实现基于socket的网络聊天。
四、总结
参考连接:
1、 http://mobile.51cto.com/android-386691.htm
2、http://blog.csdn.net/conowen/article/details/7313671
3、http://www.cnblogs.com/harrisonpc/archive/2011/03/31/2001565.html
socket简单通信的几个关键点:
1、如果要实现接受消息功能,需要本身做为服务端跑起来,同时得到可读流。关键点:serverSocket、getIputStream
2、如果要实现消息发送功能,需要本身创建套接字,并得到可写流,同时设置要发送到的ip和端口号。关键点:socket、getOutputStream、对方IP、对方Port
That‘s All
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。