Tcp api
两个类:
ServerSocket:
专门给TCP服务器用的
Socket:
既需要给服务器用,又需要给客户端用
主要通过这样的类来描述一个socket文件即可,而不需要专门的类来表示传输包,面向字节流以字节为单位传输的。
举例:
就好像买房子会有西装革履的小哥哥带你进入销售楼盘,然后喊出一个小姐姐销售,由她给你介绍这个楼盘的详细情况。然后他转身溜走了到马路牙子继续拉人。小哥哥好像就是serverSocket,销售小姐姐就是clientSocket。这里之所以分成两步就是要建立连接,一个专门负责建立连接,一个专门负责通信。
Socket clientSocket = serverSocket.accept();
try{
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
上述代码针对clientSocket已关闭了,但是对于serverClient就没有关闭。同时在UDP版本的代码里,也没有针对Socket的关闭,原因?
关闭是为了“释放资源”,释放资源的前提是已经不需要使用这个资源了,但是对于UDP的程序和serverSocket,这些socket都是贯穿程序始终的。这些资源最迟也是跟随进程一起退出释放了。(进程才是系统分配资源的基本单位)。clientSocket每一个连接都有一个,数目很多连接断开也就不再需要了。每次都得保证处理完的连接都进行释放。
TCP/UDP构造方法的端口比较:
对于UDP的socket,和TCP的serverSocket来说,构造方法指定的端口表示自己绑定哪个端口。
对于TCP的socket来说,构造方法的指定端口表示要连接的服务器的端口。
多线程处理多连接问题:
服务器同一时刻需要处理多个连接,如果如下所示则不能实现。
问题描述:
当上面的代码第一次accept结束之后,就会进入processConnection,在processConnection又会有一个循环,如果processConnection里面的循环不结束,processConnection就无法执行完成,外层就无法二次调用accept,就不能接受第二个客户端的链接了。
解决方法:
让processConnection的执行和前面的accept的执行互不干扰,不能让processConnection里面的循环导致accpet无法及时调用。因此使用多线程。
主线程循环调用accpet,当有客户端连接上来的时候,就直接让主线程创建一个新线程,由新线程负责对客户端的若干请求提供服务(在新线程里通过while循环来处理请求)。这个时候多个线程是并发执行的关系,就是各自执行各自的了就不会互相干扰。
为什么UDP不需要多线程?
因为UDP不需要处理连接,UDP只需要一个循环就可以处理所有客户端的请求。但是此处TCP既要处理连接又要处理连接中的若干次请求,就需要两个循环,里层循环就会影响到外层循环的进度了。
服务端:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
* ClassName TcpEchoServer
* Description
* Create by 93900
* Date 2022/8/2 22:16
*/
public class TcpEchoServer {
//listen => 监听
//但是在java socket 体现不出来监听的含义
//之所以这么叫 是因为操作系统的原生API有一个操作叫做listen
//private ServerSocket listenSocket = null;
private ServerSocket serverSocket = null