SocketDemo 类似聊天室

服务端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建立输出流,向客户端输出数据。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值