代码实现
TcpClient(聊天室客户端)
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 聊天室客户端
*/
public class TcpClientDemo1 {
public static void main(String[] args) {
int port = 9999;
/**
* 使用try-with-resource语句包含两个用分号隔开的声明
* Socket 以及 OutputStream
* 当代码块终止,不管是正常还是异常,对象的close方法都会自动按声明的相反顺序调用。
* 先关闭os再关闭socket
*
* 1.知道服务器的地址和端口号
* 2.建立socket连接
* 3.发送消息IO流
*/
try(Socket socket =new Socket(InetAddress.getByName("127.0.0.1"), port);
OutputStream os = socket.getOutputStream();)
{
os.write("你好,欢迎学习moer聊天室".getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
}
TcpServer(聊天室服务端)
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 聊天室服务端
*/
public class TcpServerDemo1 {
public static void main(String[] args) {
/**
* 1.服务端地址
* 2.等待客户端连接过来
* 3.读取客户端的消息
* 4.字节内存流进行输出
*/
try (ServerSocket serverSocket = new ServerSocket(9999);
Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();
ByteArrayOutputStream baos =new ByteArrayOutputStream();){
byte[] buffer = new byte[1024];
int len;
while((len = is.read(buffer)) != -1){
baos.write(buffer, 0 , len);
}
System.out.println(baos.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
了解知识
TCP是面向连接的、可靠的、基于字节流的传输层通信协议。
连接管理机制
正常情况下, tcp需要经过三次握手建立连接, 四次挥手断开连接.
三次握手(趣味理解)
A:你瞅啥!
B:瞅你咋地!
A:兄弟可以来了干架了!
四次挥手(趣味理解)
A: 我要走了
B: 你真的要走了?
B: 你真的真的要走了?
A: 给爷爬!
图片引用 https://blog.csdn.net/sinat_36629696/article/details/80740678
问: 三次握手建立连接时,发送方再次发送确认的必要性?
假定出现一种异常情况,即A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,一直延迟到连接释放以后的某个时间才到达B,本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误认为是A又发出一次新的连接请求,于是就向A发出确认报文段,同意建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了,这样一直等待A发来数据,B的许多资源就这样白白浪费了。
问: 四次挥手释放连接时,TIME_WAIT等待2MSL的意义
第 一,为了保证A发送的最后一个ACK报文段能够到达B。这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的B收不到对已发送的FIN和ACK 报文段的确认。B会超时重传这个FIN和ACK报文段,而A就能在2MSL时间内收到这个重传的ACK+FIN报文段。接着A重传一次确认。
第二,就是防止上面提到的已失效的连接请求报文段出现在本连接中,A在发送完最有一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。
规范类知识
SonarLint Try-with-resources should be used
java 1.7之后,增加了 try-wit-resource的语法,大概的用法就是在try中声明一个或者多个的流,会在try块代码执行完成后自动关闭流,不用再写finally进行手都关闭。
使用try-with-resource语句包含两个用分号隔开的声明,当代码块终止,不管是正常还是异常,对象的close方法都会自动按声明的相反顺序调用。