博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【代码积累】TCP server
阅读量:4099 次
发布时间:2019-05-25

本文共 6845 字,大约阅读时间需要 22 分钟。

import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.net.InetSocketAddress;import java.net.ServerSocket;import java.net.Socket;import java.net.SocketAddress;import java.util.Collections;import java.util.HashMap;import java.util.Map;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.logging.Level;import java.util.logging.Logger;public class TCPServer implements Runnable{	/*绑定监听IP:port	 * 1、起一个主线程进行监听,采用 thread per request的方式处理请求;	 * 2、每个请求,回送一个应答*/	public static final int MAX_THREAD = 10;		private String ip = null;	private int port = 0;	private SocketAddress listeningAddress = null;	private ServerSocket serverSocket = null;	private Logger logger = Logger.getLogger(this.getClass().getName());  //Use default logger of JAVA	private Socket connSocket = null;	private ExecutorService threadpool = Executors.newFixedThreadPool(MAX_THREAD);	private Map
connectionPool = Collections.synchronizedMap(new HashMap
()); public volatile boolean isRunning = true; public TCPServer(String ip,int port) { this.ip = ip; this.port = port; listeningAddress = new InetSocketAddress(ip, port); try { serverSocket = new ServerSocket(port, 0, ((InetSocketAddress)listeningAddress).getAddress()); logger.log(Level.INFO, "Server started...listening on "+this.ip+":"+this.port); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void run() { // TODO Auto-generated method stub while( true == isRunning ) { try { connSocket = serverSocket.accept(); if( null != connSocket ) { //handle connect in newly constructed thread Future
future = threadpool.submit(new RequestHandler(connSocket)); String connectionKey = new String(connSocket.getInetAddress().getHostAddress()+":"+connSocket.getPort()); connectionPool.put(connectionKey, new ConnectionInfo(future,connSocket)); /*讲连接放入server的连接池,便于后续使用*/ } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private class ConnectionInfo { public Future
future = null; public Socket socket = null; public ConnectionInfo(Future
future,Socket socket) { this.future = future; this.socket = socket; } } private class RequestHandler implements Runnable { private final int RECV_BUF_LEN = 1024; private Socket connSocket = null; private InputStream in = null; private OutputStream out = null; private BufferedInputStream bufin = null; private BufferedOutputStream bufout = null; private boolean isRunning = true; private byte[] recvbuffer = new byte[RECV_BUF_LEN]; private int handleswitch = 2; //recvbuffer := make([]byte,1024,1024) /*define a slice in golang*/ //var recvbuffer [1024] byte /*define an array in golang*/ public RequestHandler(Socket connSocket) { this.connSocket = connSocket; } @Override public void run() { if( null != connSocket ) { try { in = connSocket.getInputStream(); out = connSocket.getOutputStream(); bufin = new BufferedInputStream(connSocket.getInputStream()); //bufout = new BufferedOutputStream(connSocket.getOutputStream(),200); /*如果创建的时候不指定buffer大小,默认是8K;如果buffer较小,buffer满的时候会自动执行flush;stream关闭的时候,会自动flush*/ bufout = new BufferedOutputStream(connSocket.getOutputStream()); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } // TODO Auto-generated method stub //get info from the socket via stream while( !Thread.currentThread().isInterrupted() && true == isRunning) { if( null != connSocket ) { if( handleswitch == 1 ) { //第一种方式,通过传统的stream方式读取 if( null != in && null != out) { // in.read(); /*返回stream中的下一个byte,作为int类型返回,如果stream到达末尾,则返回-1*/ try { int cnt = in.read(recvbuffer); if( cnt > 0) { //recv success String received = new String(recvbuffer,0,cnt); /*注意使用有效的数据长度,而不是整个buffer的长度创建string,避免乱码*/ //logger.log(Level.INFO, "Received: "+received); //send an echo as soon as possible String response = new String("I'm the server,received your message:"+received); logger.log(Level.INFO, response); out.write(response.getBytes()); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); //send an event to TCPSever to notify it to handle connection failure. isRunning = false; } } } else if( handleswitch == 2 ) { //第二种方式,使用bufferedstream的方式读取 if( bufin != null && bufout != null ) { try { int cnt = bufin.read(recvbuffer); //底层是调用InputStream的read逐个字节读到buffer里的 if( cnt > 0 ) { String received = new String(recvbuffer,0,cnt); /*注意使用有效的数据长度,而不是整个buffer的长度创建string,避免乱码*/ //logger.log(Level.INFO, received); //send an echo as soon as possible String response = new String("I'm the server,received your message:"+received); logger.log(Level.INFO, response); bufout.write(response.getBytes()); bufout.flush(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); try { connSocket.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } isRunning = false; } } /*综上:个人认为,bufferedstream的意义,在发送的时候大于接收的时候,从源码看到,接收的时候,基本还是调用底层的read逐个字节读的; * 在发送端,业务线程可以不断把数据往buffer里填,直到需要发送或者buffer满的时候,调用或触发flush将数据提交给OS(并非提交给 * 物理设备,如网卡),这样在某些场景下,业务线程不必每填一次数据都write一把,提高了效率。*/ } else if( handleswitch == 3 ) { //第三种方式,使用reader/writer方式读取 try { //从字节流到字符流再到文本 BufferedReader br = new BufferedReader(new InputStreamReader(connSocket.getInputStream(), "UTF-8")); if( null != br ) { String line = null; //BufferedReader 有几种读的方式:1、逐个字符读取;2、将字符流顺序读取到指定的缓存中;3、逐行读取(以换行符为准) while( null != ( line = br.readLine()) ) { //readline 以换行符、字符串结束符为准 //如果读不到行结束,该调用会阻塞并一直读取,直到字符流结束,内部用StringBuffer保存每次读取的string logger.log(Level.INFO, "Server received:"+line); } } } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } else { logger.log(Level.INFO, "Socket is null! Stop reading!"); isRunning = false; } } } }}

转载地址:http://athii.baihongyu.com/

你可能感兴趣的文章
剑指offer算法题分析与整理(三)
查看>>
JVM并发机制探讨—内存模型、内存可见性和指令重排序
查看>>
WPF中PATH使用AI导出SVG的方法
查看>>
QT打开项目提示no valid settings file could be found
查看>>
java LinkedList与ArrayList迭代器遍历和for遍历对比
查看>>
如何用好碎片化时间,让思维更有效率?
查看>>
带WiringPi库的交叉笔译如何处理二之软链接概念
查看>>
Java8 HashMap集合解析
查看>>
自定义 select 下拉框 多选插件
查看>>
fastcgi_param 详解
查看>>
poj 1976 A Mini Locomotive (dp 二维01背包)
查看>>
《计算机网络》第五章 运输层 ——TCP和UDP 可靠传输原理 TCP流量控制 拥塞控制 连接管理
查看>>
剑指_复杂链表的复制
查看>>
FTP 常见问题
查看>>
shell 快捷键
查看>>
MODULE_DEVICE_TABLE的理解
查看>>
No devices detected. Fatal server error: no screens found
查看>>
db db2_monitorTool IBM Rational Performace Tester
查看>>
postgresql监控工具pgstatspack的安装及使用
查看>>
【JAVA数据结构】双向链表
查看>>