SocketDemo 类似聊天室
来源:互联网 发布:爱迪生电弧打火机 淘宝 编辑:程序博客网 时间:2024/06/06 04:49
服务端Java代码:
public class SocketDemo {private static final int SOCKET_PORT = 50000;public static ArrayList<Socket> socketList = new ArrayList<Socket>();public static void main(String[] args) {ServerSocket serverSocket = null;try {serverSocket = new ServerSocket(SOCKET_PORT);while (true) {Socket socket = serverSocket.accept();socketList.add(socket);new Thread(new SocketThread(socket)).start();}} catch (Exception e) {e.printStackTrace();} finally {try {if (serverSocket != null) {serverSocket.close();}} catch (Exception e) {e.printStackTrace();}}}}class SocketThread implements Runnable {private Socket socket = null;private BufferedReader br = null;private BufferedWriter bw=null;public SocketThread(Socket socket) {this.socket = socket;}public void run() {try {while(true){String shared_content = "";StringBuffer buffer = new StringBuffer();if(br==null){br = new BufferedReader(new InputStreamReader(socket.getInputStream()));}String content;while (!"END".equals(content = br.readLine())) {buffer.append(content);}for (Socket mSocket : SocketDemo.socketList) {bw = new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream()));shared_content = packageMessage(buffer.toString());bw.write(shared_content);bw.flush();}}} catch (Exception e) {e.printStackTrace();} finally {try {if (br != null) {br.close();}} catch (Exception e) {e.printStackTrace();}}}public String packageMessage(String msg) {String message = "";if (msg.startsWith("1")) {Date date = new Date();SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");String time = format.format(date);message = message + "user1 " + time + " :" + msg.substring(1)+"\r\n"+"END\r\n";}if (msg.startsWith("2")) {Date date = new Date();SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");String time = format.format(date);message = message + "user2 " + time + " :" + msg.substring(1)+"\r\n"+"END\r\n";}return message;}}
android客户端代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ public static final int PORT=50000; public static final String inetAddress="10.0.2.2"; private EditText mEditText; private Button mButton1; private Button mButton2; private LinearLayout mLinearLayout1; private LinearLayout mLinearLayout2; private Socket socket1=null; private Socket socket2=null; private PrintWriter pw1=null; private PrintWriter pw2=null; private ClientThreadWriter clientThreadWriter1=null; private ClientThreadWriter clientThreadWriter2=null; private BufferedReader br1=null; private BufferedReader br2=null; private ClientThreadReader clientThreadReader1=null; private ClientThreadReader clientThreadReader2=null; private Handler handler=new Handler(){ public void handleMessage(Message msg){ switch(msg.what){ case 0: mEditText.setText(""); break; case 1: TextView mTextView1=new TextView(MainActivity.this); mTextView1.setText(msg.getData().getString("new_message")); mLinearLayout1.addView(mTextView1); break; case 2: TextView mTextView2=new TextView(MainActivity.this); mTextView2.setText(msg.getData().getString("new_message")); mLinearLayout2.addView(mTextView2); break; } } }; public void init(){ mEditText= (EditText) findViewById(R.id.edit_text); mButton1= (Button) findViewById(R.id.button_1); mButton2= (Button) findViewById(R.id.button_2); mButton1.setOnClickListener(this); mButton2.setOnClickListener(this); mLinearLayout1= (LinearLayout) findViewById(R.id.record_1); mLinearLayout2= (LinearLayout) findViewById(R.id.record_2); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } public void onClick(View view){ switch(view.getId()){ case R.id.button_1: if(clientThreadWriter1==null){ clientThreadWriter1=new ClientThreadWriter(1); clientThreadReader1=new ClientThreadReader(1); new Thread(clientThreadReader1).start(); } new Thread(clientThreadWriter1).start(); break; case R.id.button_2: if(clientThreadWriter2==null){ clientThreadWriter2=new ClientThreadWriter(2); clientThreadReader2=new ClientThreadReader(2); new Thread(clientThreadReader2).start(); } new Thread(clientThreadWriter2).start(); break; } } class ClientThreadWriter implements Runnable{ private int userId; public ClientThreadWriter(int user){ userId=user; } public void run(){ try{ if(userId==1){ if(socket1==null){ //保证无论是user1还是user2都只持有一个socket,一个PrintWriter socket1=new Socket(inetAddress,PORT); pw1=new PrintWriter(new OutputStreamWriter(socket1.getOutputStream())); br1=new BufferedReader(new InputStreamReader(socket1.getInputStream())); } pw1.write(userId+mEditText.getText().toString()+"\r\n"+"END\r\n"); pw1.flush(); handler.sendEmptyMessage(0); } if(userId==2){ if(socket2==null){ //保证无论是user1还是user2都只持有一个socket,一个PrintWriter socket2=new Socket(inetAddress,PORT); pw2=new PrintWriter(new OutputStreamWriter(socket2.getOutputStream())); br2=new BufferedReader(new InputStreamReader(socket2.getInputStream())); } pw2.write(userId+mEditText.getText().toString()+"\r\n"+"END\r\n"); pw2.flush(); handler.sendEmptyMessage(0); } /*socket.shutdownOutput();*/ }catch(Exception e){ e.printStackTrace(); } } } class ClientThreadReader implements Runnable{ private int userId; public ClientThreadReader(int user){ userId=user; } public void run(){ try{ if(userId==1){ while(true){ if(socket1!=null){ String content; StringBuffer buffer=new StringBuffer();Log.d("TAG123","reading"); while(!"END".equals(content=br1.readLine())){ buffer.append(content); } Message msg=Message.obtain();Log.d("TAG123",buffer.toString()); Bundle bundle=new Bundle(); bundle.putString("new_message",buffer.toString()); msg.setData(bundle); msg.what=1; handler.sendMessage(msg); } } } if(userId==2){ while(true){ if(socket2!=null){ String content; StringBuffer buffer=new StringBuffer(); while(!"END".equals(content=br2.readLine())){ buffer.append(content); } Message msg=Message.obtain(); Bundle bundle=new Bundle(); bundle.putString("new_message",buffer.toString()); msg.setData(bundle); msg.what=2; handler.sendMessage(msg); } } } }catch(Exception e){ e.printStackTrace(); } } }}运行效果:
编写过程中遇见的问题:
BufferedReader的readLine方法,InputStream的read方法都是阻塞方法,服务端建立输入流读取客户端的PrintWriter输出流,当客户端未输入任何内容时,服务端的readLine并不会返回null,而是出于阻塞状态(阻塞线程)。当客户端输入内容后,若输入内容不能填满PrintWriter的缓冲区,且没有用flush刷新缓冲区,那么服务端readLine不会读取到数据,依旧会阻塞线程。当使用flush方法刷新缓冲区后,服务端while((content=br.readLine())!=null){.....}仍然会阻塞线程,通过在数据后面添加“\r\n”能够解除readLine的线程阻塞,返回读取到的String,但是下一轮循环继续读取流,流中没有数据,readLine继续阻塞线程。最后自定义了一个结束符“END\r\n”,且修改了while循环while (!"END".equals(content = br.readLine())){......},当读取到"END\r\n"时readLine返回“END”,使得while循环为false,退出循环。解决BufferedReader readLine阻塞线程问题。
Demo整体思路:
客户端通过单击button开一个子线程去初始化socket,建立一个输出流,一个输入流,再开一个无限循环的子线程,不断读取来自服务端的数据。此后每次单击就仅单开一个线程向服务端输出数据即可。服务端通过ServerSocket.accept接收Socket,并开启一个无限循环的子线程去建立一个输入流,读取客户端的数据,再与服务端接收到的所有socket建立输出流,向客户端输出数据。
- SocketDemo 类似聊天室
- SocketDemo
- SocketDemo
- 类似9158视频聊天室源码开发方案
- Android-Socket-SocketDemo-AndroidStudio
- 聊天室
- 聊天室
- 聊天室
- 聊天室
- 聊天室
- 聊天室
- 聊天室
- 聊天室
- 聊天室
- 聊天室
- 聊天室
- 聊天室
- 聊天室
- 伪代码编程过程
- Json读写2017.9.23
- 数据库——SQL中的join连接
- 无穷小微积分的模型论思想
- 用OC和UI实现购物车功能 在iOS平台上
- SocketDemo 类似聊天室
- C语言程序,求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字,例如:2+22+222+2222+22222
- 动态规划-343. Integer Break
- Spring系列之Spring常用注解总结
- 使用Loader获取Android联系人列表
- leetcode--189.Rotate
- ndk c调java
- stl set讲解
- u启动盘制作