java bio socket 实例一

服务端测试代码:

package com.my.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerSocketTest {

	public static void main(String agrs[])  {
		
		try{
			
			ServerSocket socket=new ServerSocket(8088);
			int i=1;
			while(true){
				Socket cSocket=socket.accept();
				System.out.println("线程数:"+i);
				System.out.println(cSocket.getPort());
				new Thread(new ServerThread(cSocket)).start();
				i++;
			}
			
		}catch(Exception e){
			e.printStackTrace();
		}
		
	}
	
	static class ServerThread implements  Runnable {
		
		private Socket socket;
		
		public ServerThread(Socket socket){
			this.socket=socket;
		}
		
		public void run() {
		
			try{
				InputStream input=socket.getInputStream();
				BufferedReader reader=new BufferedReader(new InputStreamReader(input));
				
				while(true){
					String line=reader.readLine();
					if(line!=null){
						System.out.println(line);
					}
					if(line!=null && line.equals("quit")){
						System.out.println(line);
						socket.close();
						break;
					}
				}
				
			}catch(Exception e){
				e.printStackTrace();
				try {
					socket.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
			
		}
	}
	
}

客户端测试代码:

package com.my.socket;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerSocketClient {

	public static void main(String agrs[])  {
		
		ByteArrayOutputStream output=null;
		try{
			
			int i=1;
			while(true){
				Socket socket=new Socket();
				System.out.println("start new Thread");
				new Thread(new ClientThread(socket,i)).start();
				i++;
				Thread.sleep(2000);
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(output!=null){
				try {
					output.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	
	static class ClientThread implements Runnable{

		private Socket cSocket;
		private int i;
		
		public ClientThread(Socket cSocket, int i) {
			super();
			this.cSocket = cSocket;
			this.i = i;
		}


		@Override
		public void run() {
			try {
				cSocket.connect(new InetSocketAddress(8088));
				OutputStream out=cSocket.getOutputStream();
				String con="thread"+i+"\r\n";
				out.write(con.getBytes());
				Thread.sleep(1000);
				out.write("quit".getBytes());
				out.close();
				cSocket.close();
				
			} catch (Exception e) {
				try {
					cSocket.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				e.printStackTrace();
			}
		}
		
	}
	
	
	
	
}



需要注意的几个地方:

1.客户端与服务端需要协商好相互通信的格式, 上面代码的格式(写入一句内容然后换行,结束用字符 'quit' 标识)比较简单, 

2.服务端线程类ServerThread的run()方法如果没有break语句, 子线程永远不会结束,单个jvm的线程数会飙升,导致堆内存溢出,如下 jvisualvm图

java bio socket 实例一_第1张图片


3.测试代码是客户端主动关闭socket, 然后通知服务端关闭相应的socket,如果服务端不关闭socket, 服务端socket状态进入CLOSE_WATE, 客户端socket状态进入FIN_WAIT_2状态,如下图,服务端将可以继续向客户端的socket写数据,,客户端也能接受到数据.

java bio socket 实例一_第2张图片

只有客户端,服务端都关闭了socket, 服务端socket状态才会进入CLOSE,客户端进入 TIME_WAIT.  涉及到tcp状态转移部分知识,推荐看下这边书


上面的socket通信是JAVA中用的较多的阻塞式通信(BIO),缺点是显而易见的,客户端的线程数与服务端线程数成正比. 客户端上万的并发量,服务端线程数也会上万,单个jvm肯定会挂的.




你可能感兴趣的:(io)