[Android通信]基于socket的聊天app(一):实现一对多通信
2015-10-03 18:34
621 查看
分析:
1.所谓的一对多,就是一个客户端发消息给服务器,其他的客户端都会收到消息,类似于qq群那样。
2.当客户端连接上服务器时,在客户端就会有一个socket客户端,然后在服务器就会有一个对应的socket服务器端。当socket客户端通过输出流发送信息时,对应的socket服务器端就会通过输入流接收到信息,然后可以对信息进行处理。之后,socket服务器端可以通过输出流发送信息,socket客户端通过输入流获取从服务器端发过来的信息。这就是socket通信了。
服务器端代码:
1.因为ServerSocket.accept()是一个阻塞函数,不能让它阻塞主线程,所以新建一个Thread类专门负责连接客户端。
2.ChatSocket是对服务器端socket的进一步封装,它继承Thread,表示每有一个客户端连接上服务器,就会开一个新的线程保存客户端对应的socket服务器端,负责在服务器端接受和发送信息。其中重写run方法负责接受对应的socket客户端发过来的信息,而out方法负责向对应的socket客户端发送信息。注意readLine()也是一个阻塞函数。同时注意因为使用的是readLine(),所以写信息的时候要加上"\n"作为结束符。
3.ChatManager是一个单例,负责管理所有的ChatSocket,其中publish负责向其他客户端发送消息。
客户端代码:
1.这里的IP地址是怎么知道的呢?在控制面板---网络和Internet---网络和共享中心,点击本地连接---详细信息,其中IPv4地址即为要填写的IP地址。
布局比较简单,上面显示收发信息,下面是输入框和发送信息的按钮:
最后,不要忘了添加权限:
1.所谓的一对多,就是一个客户端发消息给服务器,其他的客户端都会收到消息,类似于qq群那样。
2.当客户端连接上服务器时,在客户端就会有一个socket客户端,然后在服务器就会有一个对应的socket服务器端。当socket客户端通过输出流发送信息时,对应的socket服务器端就会通过输入流接收到信息,然后可以对信息进行处理。之后,socket服务器端可以通过输出流发送信息,socket客户端通过输入流获取从服务器端发过来的信息。这就是socket通信了。
服务器端代码:
1.因为ServerSocket.accept()是一个阻塞函数,不能让它阻塞主线程,所以新建一个Thread类专门负责连接客户端。
2.ChatSocket是对服务器端socket的进一步封装,它继承Thread,表示每有一个客户端连接上服务器,就会开一个新的线程保存客户端对应的socket服务器端,负责在服务器端接受和发送信息。其中重写run方法负责接受对应的socket客户端发过来的信息,而out方法负责向对应的socket客户端发送信息。注意readLine()也是一个阻塞函数。同时注意因为使用的是readLine(),所以写信息的时候要加上"\n"作为结束符。
3.ChatManager是一个单例,负责管理所有的ChatSocket,其中publish负责向其他客户端发送消息。
public class TestServerSocket { public static void main(String[] args) { new ServerListener().start(); } }
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import javax.swing.JOptionPane; public class ServerListener extends Thread{ @Override public void run() { //端口范围:1-65535 ServerSocket serverSocket; try { serverSocket = new ServerSocket(1989); while(true) { Socket socket = serverSocket.accept(); JOptionPane.showMessageDialog(null, "有客户端连接到了1989端口"); System.out.println("有客户端连接到了1989端口"); ChatSocket cs = new ChatSocket(socket); cs.start(); ChatManager.getChatManager().add(cs); } } catch (IOException e) { e.printStackTrace(); } } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.Socket; public class ChatSocket extends Thread{ Socket socket; public ChatSocket (Socket socket) { this.socket = socket; } public void out(String s) { try { socket.getOutputStream().write((s+"\n").getBytes("UTF-8")); } catch (Exception e) { e.printStackTrace(); } } @Override public void run() { try { BufferedReader bReader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8")); String s; while ((s = bReader.readLine()) != null) { System.out.println(s); ChatManager.getChatManager().publish(this, s); } bReader.close(); } catch (IOException e) { e.printStackTrace(); } } }
import java.util.Vector; public class ChatManager { Vector<ChatSocket> vector = new Vector<ChatSocket>(); private ChatManager () { } private static final ChatManager cm = new ChatManager(); public static ChatManager getChatManager() { return cm; } public void add(ChatSocket chatSocket) { vector.add(chatSocket); } public void publish(ChatSocket chatSocket,String s) { for(int i = 0;i < vector.size();i++) { ChatSocket cs = vector.get(i); if(!cs.equals(chatSocket)) { cs.out(s); } } } }
客户端代码:
1.这里的IP地址是怎么知道的呢?在控制面板---网络和Internet---网络和共享中心,点击本地连接---详细信息,其中IPv4地址即为要填写的IP地址。
package com.example.mysocketclient; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; import java.net.UnknownHostException; import android.app.Activity; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private TextView textView; private EditText editText; private Button button; private Socket socket; private BufferedWriter bWriter;//输出流,发送、写入信息 private BufferedReader bReader;//输入流,接受、读取信息 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView)findViewById(R.id.textView1); editText = (EditText)findViewById(R.id.editText1); button = (Button)findViewById(R.id.button1); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { send(); } }); connect(); } private void connect() { new AsyncTask<Void, String, Void>() { //在主线程中执行,不能用来初始化socket protected void onPreExecute() { } protected Void doInBackground(Void[] params) { try { socket = new Socket("172.25.225.24",1989); bWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); bReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); publishProgress("connect success"); } catch (IOException e) { Log.e("connect error", "error"); } String s; //readLine()是一个阻塞函数,当没有数据读取时,就一直会阻塞在那,而不是返回null //接受信息 try { while ((s = bReader.readLine()) != null) { publishProgress(s); } } catch (IOException e) { e.printStackTrace(); } return null; } protected void onProgressUpdate(String[] values) { if(values[0].equalsIgnoreCase("connect success")) { Toast.makeText(MainActivity.this, "连接成功", Toast.LENGTH_SHORT).show(); } else { textView.append("别人说" + values[0] + "\n"); } } }.execute(); } //发送信息 private void send() { try { textView.append("我说:" + editText.getText().toString() + "\n"); bWriter.write(editText.getText().toString() + "\n"); bWriter.flush(); editText.setText(""); } catch (IOException e) { e.printStackTrace(); } } }
布局比较简单,上面显示收发信息,下面是输入框和发送信息的按钮:
最后,不要忘了添加权限:
<uses-permission android:name="android.permission.INTERNET"/>
相关文章推荐
- java-模拟tomcat服务器
- Linux socket 初步
- java socket 注意的地方
- java socket 注意的地方
- C#基于socket模拟http请求的方法
- 简单的Ruby中的Socket编程教程
- Socket不能选择本地IP连接问题如何解决
- C#之Socket操作类实例解析
- 使用C#来编写一个异步的Socket服务器
- C#使用Socket快速判断数据库连接是否正常的方法
- 科学知识:理解socket
- php与flash as3 socket通信传送文件实现代码
- 解决time_wait强制关闭socket
- C#使用Socket上传并保存图片的方法
- 深入php socket的讲解与实例分析
- Linux网络编程之UDP Socket程序示例
- Linux网络编程之socket文件传输示例
- filezilla Failed to create listen socket on port 21 for IPv4 解决办法
- php socket方式提交的post详解
- PHP异步调用socket实现代码