- 实现通信的条件
- IP地址
IP地址具有唯一性
IP地址的范围:0.0.0.0 - 255.255.255.255
本地IP地址:127.0.0.1 或 0.0.0.0
- IP协议
Internet Protocol 互联网协议,为计算机网络相互连接进行通信而设计的协议
- 端口号
端口号包括物理端口和逻辑端口
物理端口是用于连接物理设备之间的接口
逻辑端口是逻辑上用于区分服务的端口
端口号只有整数,范围从0-65535
1024-5000 分配给操作系统各个进程
大于5000为其他个人软件预留
| 常见开发软件的默认端口 | |
| HTTP | 80 |
| FTP | 21 |
| TELNET | 23 |
| tomcat | 8080 |
| MySQL | 3306 |
2 TCP/IP协议
TCP协议:Transmission Control Protocol 传输控制协议
IP协议:Internet Protocol 互联网协议(网际互联协议)
通俗而言:TCP负责发现传输的问题,一有问题就发出信号,要求重新传输,直到所有数据安全正确地传输到目的地。而IP是给因特网的每一台联网设备规定一个地址。
3 TCP/IP五层模型-网络层次划分
- 应用层
网络服务与最终用户的一个接口
协议有:HTTP FTP SMTP TFTP SNMP DNS TELNET HTTPS POP3 DHCP
- 传输层
定义传输数据的协议端口号,以及流程控制和差错校验
协议有:TCP UDP
- 网络层
进行逻辑地址寻址,实现不同网络之间的路径选择
协议有:ICMP IGMP IP(IPv4 IPv6) ARP RARP
- 数据链路层
建立逻辑连接,进行硬件地址寻址,差错校验等功能
- 物理层
建立、维护、断开物理连接。(由底层网络定义协议 )
4 TCP建立连接-三次握手
TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接。
由于TCP是面向连接的所以只能用于端到端的通讯。TCP提供的是一种可靠的数据流服务,采用"带重传的肯定确认"技术来实现传输的可靠性。TCP还采用一种称为"滑动窗口"的方式进行流量控制,所谓窗口实际表示接收能力,用以限制发送方的发送速度。

| 字段 | 全称 | 名称 | 解释 |
| seq | sequance | 序列号 | |
| ack | acknowledge | 确认号 | |
| SYN | synchronize | 请求同步标志 | 请求建立连接,设置序列号为1 |
| ACK | acknowledge | 确认标志 | 确实是否有效,一般置为1 |
| FIN | Finally | 结束标志 |

TCP连接建立过程:
- 第一次握手(请求建立连接):客户端发送连接请求报文。Client将标志位SYN置为1,随机为序列号产生一个值seq=x,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
- 第二次握手(应答):服务端接收连接请求后回复ACK确认报文,并为这次连接分配资源。Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=x+1,随机产生一个值seq=y,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
- 第三次握手(建立连接):客户端接收到ACK报文后也向服务端发送ACK报文,并分配资源,此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。Client收到确认后,检查ack是否为x+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=y+1,并将该数据包发送给Server。Server检查ack是否为y+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
5 TCP断开连接-四次挥手

- Client端发起中断连接请求,也就是发送FIN报文;
- Serer端接收到FIN报文后,先发送ACK报文,确认接收到了Client端的请求,然后进入准备状态,此时Server端如果还有没发送完的数据,可以继续发送;
- Client端接收到Server端的ACK报文,进入FIN_WAIT状态,继续等待Server端的FIN报文;
- 当Server端确定数据已发送完成,则向Client端发送FIN报文;
- Client端接收到FIN报文后,再次发送ACK报文,然后进入TIME_WAIT状态,如果Server端没有接收到ACK报文可以重传;
- Server端收到ACK后,断开连接,Client端等待2MSL后依然没有收到回复,则证明Server端已正常关闭,Client端也可以关闭连接了。TCP连接就这样关闭了。
问题:为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
socket网络编程
6 socket套接字
IP地址+端口号组成了socket,socket是网络上运行的程序之间双向通信链路的终结点,是TCP和UDP的基础。
网络上具有唯一标识的IP地址和端口号组合在一起,才能构成唯一能识别的标识符套接字.。
socket原理机制:
- 通信两端都有socket
- 网络通信其实就是socket之间的通信
- 数据在两个socket间通过IO流传输
7 socket编程实现即时通讯
服务端:
public class ServerNode {
public static void main(String[] args) throws IOException, InterruptedException {
String readline = null;
String inTemp = null;
String turnLine = "\n";
final String client = "Client:";
final String server = "Server:";
//端口号
int port = 8081;
//1 创建ServerSocket,监听端口8081
ServerSocket serverSocket = new ServerSocket(port);
//2 调用服务器的accept方法,接受来自客户端的连接请求。在接收到客户端连接请求之前,此方法会进行阻塞(程序会在这等待),当有申请连接时会建立连接并返回一个socket
Socket socket = serverSocket.accept();
//3 创建服务端输入流:获取系统输入的数据
BufferedReader systemIn = new BufferedReader(new InputStreamReader(System.in));
//4 创建客户端输入流:获取客户端传输的数据
BufferedReader socketIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//5 创建输出流:用于向客户端返回数据
PrintWriter socketOut = new PrintWriter(socket.getOutputStream());
while(readline != "bye"){//当服务端系统输入bye时,终止连接
//6 读取客户端输入流
inTemp = socketIn.readLine();
System.out.println(client + turnLine + inTemp);
System.out.println(server);
//7 服务端系统输入
readline = systemIn.readLine();
//8 向客户端返回数据
socketOut.println(readline);
/*
* println() 和 write()的区别:
* write方法只会写入字符,不会写入换行符和回车符
* println方法意思是写入一行数据,会自带换行符
*
* 当readLine()方法只有读取到 \n 或者 \r 的时候,代表数据读取完毕
* 否则会一直继续读取输入流的数据,直到有换行符出现
* 如果用write方法,会造成程序执行阻塞
*/
socketOut.flush(); //赶快刷新使Client收到,也可以换成socketOut.println(readline, ture)
}
systemIn.close();
socketIn.close();
socketOut.close();
socket.close();
serverSocket.close();
}
}
客户端:
public class ClientNode {
public static void main(String[] args) throws IOException, InterruptedException {
String readline = null;
String inTemp = null;
String turnLine = "\n";
final String client = "Client:";
final String server = "Server:";
//服务端端口号
int port = 8081;
/*
* 服务端ip地址
*/
// byte ipAddressTemp[] = {127, 0, 0, 1};
// InetAddress ipAddress = InetAddress.getByAddress(ipAddressTemp);
//首先直接创建socket,端口号1~1023为系统保存,一般设在1023之外
Socket socket = new Socket("127.0.0.1", port);
BufferedReader systemIn = new BufferedReader(new InputStreamReader(System.in));
BufferedReader socketIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter socketOut = new PrintWriter(socket.getOutputStream());
while(readline != "bye"){
//客户端:读取系统字节流
System.out.println(client);
readline = systemIn.readLine();
//客户端:输出流向服务端发送数据
socketOut.println(readline);
socketOut.flush(); //赶快刷新使Server收到,也可以换成socketOut.println(readline, ture)
//读取服务端返回的数据
inTemp = socketIn.readLine();
System.out.println(server + turnLine + inTemp);
}
//关闭资源
systemIn.close();
socketIn.close();
socketOut.close();
socket.close();
}
}

本文详细介绍了TCP/IP通信的基础知识,包括IP地址、端口号、TCP/IP协议以及TCP的三次握手和四次挥手过程。此外,还探讨了socket套接字的概念和网络编程的基本步骤,展示了服务端和客户端的Java socket编程示例。重点讨论了TIME_WAIT状态的作用,确保可靠的数据传输。
2880

被折叠的 条评论
为什么被折叠?



