• tcp/ip其实是一个协议族,不是具体的某个协议
  • tcp协议是属于tcp/ip协议族中的一个具体的协议

下面来介绍一下Tcp协议的Socket通信(服务端)的四种情况
第一种
/**

  • Socket的服务端

当前程序有弊端 只能为1个客户端提供服务
*
/
public class MyServerSocket01 {
/

* 程序的执行入口
*
* @param args 传递的参数
*/
public static void main(String[] args) throws Exception {

//创建服务端的Socket对象
    ServerSocket serverSocket = new ServerSocket();
    //服务端绑定端口
    serverSocket.bind(new InetSocketAddress(8899));
    //监听客户端的连接(阻塞的方法),返回的是当前连接到服务器的客户端的对象
    Socket socket = serverSocket.accept();
    System.out.println("有客户端" + socket.getRemoteSocketAddress() + "连接到服务器了.....");
    InputStream inputStream = socket.getInputStream();
    //读数据
    byte[] buf = new byte[2];
    int len;
    //调用read方法返回阻塞,当没有数据时会阻塞,并不会返回-1
    while ((len = inputStream.read(buf)) != -1) {
        String str = new String(buf, 0, len);
        System.out.println(str);
    }
}

}

第二种

/**

  • Socket的服务端
  • 当前程序有弊端 只能为一个客户端提供服务,只不过一个客户端断开连接之后其他的客户端才能进来
    /
    public class MyServerSocket02 {
    /
    *
  • 程序的执行入口

  • @param args 传递的参数
    */
    public static void main(String[] args) throws Exception {
    //创建服务端的Socket对象
    ServerSocket serverSocket = new ServerSocket();
    //服务端绑定端口
    serverSocket.bind(new InetSocketAddress(8899));
    while (true) {
    //监听客户端的连接(阻塞的方法),返回的是当前连接到服务器的客户端的对象
    Socket socket = serverSocket.accept();
    System.out.println(“有客户端” + socket.getRemoteSocketAddress() + “连接到服务器了…”);
    InputStream inputStream = socket.getInputStream();
    //读数据
    byte[] buf = new byte[2];
    int len;
    //调用read方法返回阻塞,当没有数据时会阻塞,并不会返回-1
    while ((len = inputStream.read(buf)) != -1) {
    String str = new String(buf, 0, len);
    System.out.println(str);
    }
    }
    }
    }

第三种

/**

  • Socket的服务端
  • 当前程序有弊端 每次一个客户端进来之后都会创建一个线程去处理连接任务,但有大量的客户端连接到服务器的话就会有大量的线程创建,线程的创建和上下文的切换也是非常耗费时间和资源的
    /
    public class MyServerSocket02 {
    /
    *
  • 程序的执行入口

  • @param args 传递的参数
    */
    public static void main(String[] args) throws Exception {
    //创建服务端的Socket对象
    ServerSocket serverSocket = new ServerSocket();
    //服务端绑定端口
    serverSocket.bind(new InetSocketAddress(8899));
    while (true) {
    //监听客户端的连接(阻塞的方法),返回的是当前连接到服务器的客户端的对象
    Socket socket = serverSocket.accept();
    //每次有新的客户端连接到服务器之后都会启动线程来执行
    new Thread(new Runnable() {
    @Override
    public void run() {
    System.out.println(“有客户端” + socket.getRemoteSocketAddress() + “连接到服务器了…”);
    InputStream inputStream = null;
    try {
    inputStream = socket.getInputStream();
    //读数据
    byte[] buf = new byte[2];
    int len;
    //调用read方法返回阻塞,当没有数据时会阻塞,并不会返回-1
    while ((len = inputStream.read(buf)) != -1) {
    String str = new String(buf, 0, len);
    System.out.println(str);
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }).start();
    }
    }
    }

第四种
/**

  • Socket的服务端
  • 当前程序有弊端 有两个阻塞 accept read,其中accept我们就无法解决,但是read阻塞可以解决的(NIO)
    /
    public class MyServerSocket04 {
    /
    *
  • 程序的执行入口

  • @param args 传递的参数
    */
    public static void main(String[] args) throws Exception {
    //创建线程池对象(线程池的大小是本机的cpu可用的核数)
    ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    //创建服务端的Socket对象
    ServerSocket serverSocket = new ServerSocket();
    //服务端绑定端口
    serverSocket.bind(new InetSocketAddress(8899));
    while (true) {
    //监听客户端的连接(阻塞的方法),返回的是当前连接到服务器的客户端的对象
    Socket socket = serverSocket.accept();
    //每次有新的客户端连接到服务器之后都会启动线程来执行
    threadPool.execute(new Runnable() {
    @Override
    public void run() {
System.out.println("有客户端" + socket.getRemoteSocketAddress() + "连接到服务器了.....");
         InputStream inputStream = null;
         try {
             inputStream = socket.getInputStream();
             //读数据
             byte[] buf = new byte[2];
             int len;
             //调用read方法返回阻塞,当没有数据时会阻塞,并不会返回-1
             while ((len = inputStream.read(buf)) != -1) {
                 String str = new String(buf, 0, len);
                 System.out.println(str);
             }
         } catch (IOException e) {
             e.printStackTrace();
         }
     }
 });

}
}
}