赞
踩
唯一能够确定一个socket连接有4点
tomcat最多能建立多少个连接?tomcat作为服务端程序,一直在监听80端口,之前一直以为tomcat每接收到一个新的连接,都会创建一个新的socket,然后这个socket又会占用一个端口。但是事实上并不是这样的,肯定是会创建新的socket的,但是这个新创建的socket并不会占用新的端口。
那么问题来了,客户端发送的数据,服务器是怎么区分是哪个客户端?
关键就在于上面的4个点,标识一个socket的是上面的4个点,而不是单纯的一个本地ip和一个本地端口,所以tomcat每accpet到一个连接,都会创建一个新的socket连接,这个socket连接种包含了下面4个信息,假设现在tomcat的ip为12.1.11.11
服务器ip:12.1.11.11
服务器端口:80
客户端ip:213.32.1.2
客户端端口:80
由这4个信息标识一个唯一的socket,tomcat accept到的每一个连接的服务器ip和端口都是一样的,但是客户端的ip和端口是不一样的,根据唯一标识socket的4点,系统能正确的区分。
其实就我们创建一个新的socket来说,他是没有什么特殊的,他就是一个未连接的socket,特殊的点在于socket.listen()方法
#include<sys/socket.h>
int listen(int sockfd, int backlog);
listen函数仅由TCP服务器调用,当socket函数创建一个套接口时,它被假设为一个主动套装口,也就是说,它是一个将调用connet发起连接的客户套接口。listen函数把一个未连接的套接口转换成一个被动套接口,指示内核应接受指向该套接口的连接请求。根据TCP状态转换图,调用listen导致套接口从CLOSED状态转换到LISTEN状态。
注意,在java中是没有listen()函数的,因为java帮我们进行了封装,使用了ServerSocket来专门代表监听的Socket。
运行下面这个简单的程序
public static void main(String[] args) throws IOException, InterruptedException {
ServerSocket serverSocket = new ServerSocket(21111);
Thread.sleep(100000000);
}
在windows中我们就能通过netstat -ano来查看端口占用,可以发现21111正处于监听状态
我们查看Java中的ServerSocket类的构造函数
能够看到,其实这与我们的c语言中的listen()函数差不多,其也有一个backlog参数。
为了更好的理解backlog参数,我们必须认识到内核为任何一个给定的监听套接口维护两个队列:
1、未完成连接队列(incomplete connection queue),每个这样的SYN分节对应其中一项:已由某个客户发出并到达服务器,而服务器正在等待完成相应的TCP三路握手过程。这些套接口处于SYN_RCVD状态。
2、已完成连接队列(completed connection queue),每个已完成TCP三路握手过程的客户对应其中一项。这些套接口处于ESTABLISHED状态。
当来自客户的SYN到达时,TCP在未完成连接队列中创建一个新项,然后响应以三路握手的第二个分节:服务器的SYN响应,其中稍带对客户SYN的ACK(即SYN+ACK)。这一项一直保留在未完成连接队列中,直到三路握手的第三个分节(客户对服务器SYN的ACK)到达或者该项超时为止(曾经源自Berkeley的实现为这些未完成连接的项设置的超时值为75秒)。如果三路握手正常完成,该项就从未完成连接队列移到已完成连接队列的队尾。当进程调用accept时,已完成连接队列中的队头项将返回给进程,或者如果该队列为空,那么进程将被投入睡眠,直到TCP在该队列中放入一项才唤醒它。
这个问题的答案是不会的,利用ServerSocket建立的连接,即使是ServerSocket关闭了,这个连接依然还是存在,因为他们之间本身就没有任何关系了
测试代码,Server
public static void main(String[] args) throws IOException, InterruptedException { ServerSocket serverSocket = new ServerSocket(); serverSocket.bind(new InetSocketAddress(8080)); Socket accept = serverSocket.accept(); new Thread(() -> { try { OutputStream outputStream = accept.getOutputStream(); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); while (true) { outputStreamWriter.write(UUID.randomUUID().toString() + System.lineSeparator()); outputStreamWriter.flush(); Thread.sleep(1000); System.out.println("写了一个"); } } catch (IOException | InterruptedException e) { e.printStackTrace(); } }).start(); serverSocket.close(); System.out.println("连接关闭"); Thread.sleep(100000); }
Client
public static void main(String[] args) throws IOException, InterruptedException {
Socket socket = new Socket();
socket.connect(new InetSocketAddress("localhost", 8080));
InputStream in = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String msg;
while ((msg = reader.readLine()) != null) {
System.out.println("读了一个");
System.out.println(msg);
}
System.out.println("dsadsa");
Thread.sleep(100000);
}
运行这两个代码我们就能发现,即使是ServerSocket关闭,依然能继续通信
我们又利用netstat -ano命令来查看端口占用
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。