import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.net.UnknownHostException; public class Client { private final Logger log = LoggerFactory.getLogger(Client.class); public static void main(String[] args) { BufferedReader ir = null; BufferedReader sr = null; String cmd = null; PrintWriter pw = null; Socket socket = null; try{ socket = new Socket("127.0.1",9001); // 使用 BufferedReader 从 socket 读取字符串(读 socket 输入流) sr = new BufferedReader(new InputStreamReader(socket.getInputStream())); // 使用 PrintWriter 向 socket 写入字符串(写 Socket 输出流) pw = new PrintWriter(socket.getOutputStream(),true); System.out.println("Say 'bye' to exit"); // 读取键盘输入的字符串,并通过 socket 发送 ir = new BufferedReader(new InputStreamReader(System.in)); /** * BufferedReader 的 readLine() ,每次传输一个字符串,以 “\n”或者 “\r” 表示一行结束 * (具体是哪一种结束符,取决于操作系统)。如果没有遇到“\n”或者“\r” 结束符,则表示本轮 * 数据还没有读取完整,当前线程会被阻塞,直到遇到“行尾”。 * 如果不采用上面的协议,就需要额外约定每笔数据的封包结构或者边界。 */ while( (cmd = ir.readLine()) != null ){ // 发送一行字符,以“行分隔符结尾”(请求) pw.println(cmd); // 读取以“行分隔符”结尾的一行字符(响应) String s = sr.readLine(); System.out.println(String.format("Server say %s", s)); if("bye".equalsIgnoreCase(s)){ break; } } }catch(UnknownHostException e){ e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); }finally { StreamUtil.close(socket); StreamUtil.close(pw); StreamUtil.close(sr); StreamUtil.close(ir); } System.out.println("客户端关闭连接"); } }
------------------------------------------------------------------------------------------------------
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Server implements Runnable{ private final Logger log = LoggerFactory.getLogger(Server.class); private final ExecutorService threadPool = Executors.newCachedThreadPool(); private ServerSocket serverSocket = null; public void start() throws IOException { // 创建 Socket 服务端,并绑定 port ,开始监听 serverSocket = new ServerSocket(9001); threadPool.execute(this); System.out.println("服务端启动成功"); } @Override public void run() { Socket socket = null; try{ /** * 接收来自客户端的连接,并将新连接交给新的线程去处理。 * * serverSocket.accept() 方法将一直阻塞,直到有新的连接请求进来 */ while( (socket = serverSocket.accept()) != null ){ log.info("Client {} connected ",socket.getRemoteSocketAddress()); // 用新的线程去处理这个新的 socket 连接,并与客户端进行通信 threadPool.execute(new Processor(socket)); } } catch (IOException e) { e.printStackTrace(); } } public void close(){ // 关闭 serverSocket 和 线程池 if( serverSocket != null && !serverSocket.isClosed()){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } threadPool.shutdown(); } public static void main(String[] args) { // 创建 Server Server server = new Server(); try { // 启动服务,并启动 threadPool 进行监听 server.start(); } catch (IOException e) { e.printStackTrace(); } } }
-----------------------------------------------------------------------------------------------------
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class Processor implements Runnable { private static final Logger log = LoggerFactory.getLogger(Processor.class); /** * 客户端的 Socket 对象 */ private Socket socket; public Processor(Socket socket){ this.socket = socket; } @Override public void run() { BufferedReader br = null; PrintWriter pw = null; try { br = new BufferedReader(new InputStreamReader(socket.getInputStream())); pw = new PrintWriter(socket.getOutputStream(),true); // 通过 socket 读写字符串,收到客户端发来的 bye 后退出 // Thread.interrupted() : 判断当前线程是否被中断了,并且擦除掉线程的interrupt标识 while( !Thread.interrupted()){ String s = br.readLine(); System.out.println(String.format("%s say %s " , socket.getRemoteSocketAddress() , s )); pw.println(s); if("bye".equalsIgnoreCase(s)){ break; } } } catch (IOException e) { e.printStackTrace(); }finally{ StreamUtil.close(pw); StreamUtil.close(br); } } }
---------------------------------------------------------
import java.io.Closeable; import java.io.IOException; public class StreamUtil { public static void close(Closeable p){ if( p == null){ return ; } try { p.close(); } catch (IOException e) { e.printStackTrace(); } } }