Android中基于Socket的网络通信
1. Socket介绍
2. ServerSocket的建立与使用
3. 使用ServerSocket建立聊天服务器-1
4. 使用ServerSocket建立聊天服务器-2
5. 在Android中创建Socket客户端
------------------------------------------------------------------
工程源码:SocketDemo.zip
服务器端 - Java工程:ServerSocketDemo
客户端 - Android工程:AndroidSocketClient
------------------------------------------------------------------
1. Socket介绍
Socket 又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求。ServerSocket 用于服务器端,Socket 是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个 Socket 实例,操作这个实例,完成所需的会话。
对于一个网络连接来说,套接字是平等的,没有差别, 不会应用在服务器端或者客户端而产生不同级别。
不管是Socket还是ServerSocket 他们的工作都是通过Socket类及其子类完成。
* 基于TCP连接,数据传输有保障
* 适于建立长时间的连接
* 通常用于即时通信
2. ServerSocket的建立与使用
3. 使用ServerSocket建立聊天服务器-1
3.1 建立Java工程: ServerSocketDemo
* ChatSocket.java
public class ChatSocket extends Thread { Socket socket; public ChatSocket(Socket s) { socket = s; } public void out(String out) { try { socket.getOutputStream().write(out.getBytes("UTF-8")); } catch (Exception e) { e.printStackTrace(); } } @Override public void run() { int count = 0; while (true) { count++; out("loop : " + count + ", \t"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
* ServerListener.java
public class ServerListener extends Thread { @Override public void run() { ServerSocket serverSocket; try { serverSocket = new ServerSocket(12345); while (true) { // 监听 12345端口 Socket socket = serverSocket.accept(); // 建立连接 JOptionPane.showMessageDialog(null, "There is an client access 12345 port"); new ChatSocket(socket).start(); } } catch (IOException e) { e.printStackTrace(); } } }
* MyServerSocket.java
public class MyServerSocket { public static void main(String[] args) { new ServerListener().start(); } }
3.2 管理员权限打开 CMD窗口: telnet localhost 12345
两个线程互补影响
4. 使用ServerSocket建立聊天服务器-2
3中的两个Client不能相互通信
所以在3的基础上修改项目:
* 新建 ChatManager.java(单例模式) 来管理Socket连接
* 修改: ServerListener.java, 来存储 所有连接 到 Server的 Socket
* 在ChatSocket线程中,增加接收消息的 代码
具体项目可以看源代码
5. 在Android中创建Socket客户端
在Android中创建Socket客户端。使用Socket建立客户端链接,并且在AsyncTask中执行网络读写的任务,将用户输入的内容发送到服务器,并接收服务器发来的数据,显示到界面上。开启多个虚拟机模拟多人聊天效果。
拿4中的Java项目作为服务器端
创建 Android客户端 项目: AndroidSocketClient
建立一个如图所示的布局:
public class MainActivity extends Activity { EditText etIP, etComposing; TextView tvContent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etIP = (EditText) findViewById(R.id.etIP); etComposing = (EditText) findViewById(R.id.etComposing); tvContent = (TextView) findViewById(R.id.tvContent); findViewById(R.id.btnConn).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub connect(); } }); findViewById(R.id.btnSend).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub send(); } }); } Socket socket = null; BufferedWriter bw; BufferedReader br; public void connect() { AsyncTask<Void, String, Void> read = new AsyncTask<Void, String, Void>() { @Override protected Void doInBackground(Void... params) { try { socket = new Socket(etIP.getText().toString(), 12345); bw = new BufferedWriter(new OutputStreamWriter( socket.getOutputStream())); br = new BufferedReader(new InputStreamReader( socket.getInputStream())); publishProgress("@success"); try { String line; while ((line = br.readLine()) != null) { publishProgress(line); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (UnknownHostException e) { // TODO Auto-generated catch block publishProgress("@fail"); e.printStackTrace(); } catch (IOException e) { publishProgress("@fail"); e.printStackTrace(); } return null; } @Override protected void onProgressUpdate(String... values) { if (values[0].equals("@success")) { tvContent.append("Success connect to Server\n"); } else if(values[0].equals("@fail")) { tvContent.append("Connect to Server Fail\n"); } else{ Log.d("CARLOZ", "Other: " + values[0]); tvContent.append("Other: " + values[0] + "\n"); } super.onProgressUpdate(values); } }; read.execute(); } public void send() { try { tvContent.append("Me: " + etComposing.getText().toString() + "\n"); bw.write(etComposing.getText().toString() + "\n"); bw.flush(); etComposing.setText("");// clear } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
运行效果如下,下面的弹框是Java程序的Dialog
同时开两台虚拟机的运行效果如下: