Socket编程

                    最近想写一个IM软件,因此研究了一下Socket编程,发现写Socket的时候有许多容易被忽略的细节需要注意,特做笔记记录。


一.Socket定义


二.Socket的阻塞式实现:

客户端主要代码:


<span style="font-family:Microsoft YaHei;font-size:18px;">private Handler myHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case RECEIVE:
                    tv_msg.append("Server Msg:" + msg.getData().getString("msg") + "\n");
                    break;
            }
        }
    };</span>


<span style="font-family:Microsoft YaHei;font-size:18px;">btn_msg.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                thread = new Thread(new MessageRunnable());
                thread.start();
            }
        });</span>



<span style="font-family:Microsoft YaHei;font-size:18px;">private class MessageRunnable implements Runnable {

        @Override
        public void run() {
            socket = new Socket();
            Message message = new Message();
            message.what = RECEIVE;
            Bundle bundle = new Bundle();
            try {
                //连接服务器端的SOCKET
                socket.connect(new InetSocketAddress(serverIP, serverPort), 5000);
                //读出服务器端SOCKET的内容
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                OutputStream os = socket.getOutputStream();</span>
<span style="font-family:Microsoft YaHei;font-size:18px;">                //设置客户端的SOCKET读取inputstream的过时时间,如果服务端在这个时间内没有发送数据过来,则抛出SocketTimeoutException
                socket.setSoTimeout(2000);
                String line=null;
                String msg = "";
                Log.v("MainActivity","ready to read form server");
                System.out.println("ready to read form server");
                while ((line = bufferedReader.readLine()) != null) {
                    msg += line;
                }
                Log.v("MainActivity","read complete");
                System.out.println("read complete");
                //更新UI
                bundle.putString("msg", msg);
                message.setData(bundle);
                myHandler.sendMessage(message);

                //向服务器写内容
                os.write(et_msg.getText().toString().getBytes("UTF-8"));
                os.flush();

                //关闭各种流和SOCKET
                bufferedReader.close();
                os.close();

            } catch (SocketTimeoutException te) {
                te.printStackTrace();
                //连接请求超时
                bundle.putString("msg", "time out");
                message.setData(bundle);
                myHandler.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();</span>
            }
        }
    }


服务器端代码:

<span style="font-family:Microsoft YaHei;">public static void main(String args[]){

      ServerSocket serverSocket=null;
      try{
		serverSocket=new ServerSocket(port);
	  }catch (IOException e){   
		e.printStackTrace();
	  }
	  System.out.println("server socket created");
	  while(true){
		  try{
			  Socket socket=serverSocket.accept();
			  System.out.println("socket accepted");
			  new Thread(new Runnable(){
				@Override
				public void run(){
					BufferedReader reader=null;
					OutputStream out=null;
					try{
						reader=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
						out=socket.getOutputStream();
						
						
						System.out.println("server is ready to read");
						String line="";
						String next=null;
						while((next=reader.readLine())!=null){
							line+=next;
						}
						System.out.println("read complete");
						System.out.println("client msg: "+line);	

						//Thread.sleep(5000);
						System.out.println("ready to write to client");
						out.write("i am socket server".getBytes("UTF-8"));
						out.flush();
						System.out.println("write complete");
						//
						//socket.shutdownOutput();	
						
												
					}catch(IOException e){
						e.printStackTrace();
					}
					//catch (InterruptedException e) {
					//	e.printStackTrace();
					//}
					finally{
						try{
							out.close();
						}catch (IOException e){
							e.printStackTrace();
						}
						try{
							reader.close();	
						}catch (IOException e){
							e.printStackTrace();
						}
					}
				}
			  }).start();
		  }catch(IOException e){
		  e.printStackTrace();
	  }
}
}</span>



需要注意:

                1.client端的connect方法和server端的accept方法是线程阻塞的,也就是说,在返回结果以前,线程是阻塞的。

                2.有些资料说服务端和客户端不能同时创建输入流,实际上这个说法并不准确,经验证,同时创建输入流是完全可以的。事实上,server和client不能同时从输入流读取数据。为什么呢,因为inputstream的read方法是线程阻塞的,如果两边同时读取的话,两端都在等待对方输出数据,造成IO阻塞,因此需要一方先输出数据,另一方读取。

              3.socket.shutdownOutput()方法,该方法的作用是关闭输出流。经验证,上述代码中如果少了这句,client端会继续读取inputstream中的内容,也就是阻塞。也就是说,只有关闭流后,才能终止read方法的阻塞状态。

                      4.socket.setSoTimeout()方法,设置socket读取输入流时的等待超时时间,必须在阻塞方法(read)之前调用。


三.Socket的非阻塞式实现:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值