网站建设公司的选择,免费下载网站建设方案ppt,网站设计 收费,用手机怎么制作微信小程序简介#xff1a;
经过了三次握手过程#xff0c;我们的服务端和客户端已经建立了连接。我们接下来需要做的就是数据的传输。
主要步骤#xff1a; 数据发送#xff1a;客户端或服务器将数据打包成一个或多个数据段#xff0c;每个数据段都有一个序列号#xff08;SEQ
经过了三次握手过程我们的服务端和客户端已经建立了连接。我们接下来需要做的就是数据的传输。
主要步骤 数据发送客户端或服务器将数据打包成一个或多个数据段每个数据段都有一个序列号SEQ和确认号ACK。 数据接收接收方接收到数据段后将根据数据段的序列号SEQ进行排序以确保数据的有序性。 确认接收接收方会为每个接收到的数据段发送一个确认ACK。这个确认包含了确认号ACK该确认号是接收方期望接收的下一个数据段的序列号也就是最后一个接收到的数据段的序列号加1。 丢包重传如果发送方在一定时间内没有接收到某个数据段的确认它会认为该数据段已经丢失并进行重传。 流量控制接收方可以使用窗口大小字段来控制发送方的发送速度以防止自己被大量的数据淹没。 拥塞控制如果网络发生拥塞TCP会降低数据的发送速度以减少网络的拥塞程度。(未实现)
所以在数据传输段过程中每一段都需要Seq(序列号)ACK(确认号)
实现过程
确认号ACK是基于之前接收到的最后一个数据包的序列号1。也就是说ACK的值是接收方期望接收的下一个数据包的序列号。这是因为在TCP协议中ACK的值总是等于接收方已经成功接收的最后一个数据包的序列号1。例如假设在三次握手的过程中客户端发送给服务器的最后一个ACK是101这是第三次握手的ACK那么在数据传输开始时如果服务器是第一个发送数据的话服务器发送的第一个数据包的序列号应该是101而客户端回复的ACK就应该是102表示客户端已经接收到了序列号为101的数据包期望接收的下一个数据包的序列号是102。
服务端发送数据到客户端
注意由于数据的传输是双向的所以在发送后可以接收客户端发来的数据。在接收数据后我们在服务端需要进行超时判断如若超时会进行超时重传。超时判断我们使用了 setSoTimeout() 方法。 关于超时的时间根据《TCP/IP详解》卷二 的计时器篇中可知超时时间严苛来说需要考虑发送端到接收端接收数据时间接收端数据处理时间接收端发送确认消息到客服端时间。超时时间的选择应该是多次数据传输花费时间的均值。在《TCP/IP详解》卷二 的 tcp 篇详细中规定了数据重传不能超过三次这里我使用了retryCount这个计数器来计数。
//数据传输开始System.out.println();System.out.println(数据发送...);String SeqD1 String.valueOf(connectionMarks.getSeq());String ACKD1 String.valueOf(Integer.parseInt(strArr3[1]) 1);String dataMsg SeqD1 我是马尔咖里斯我是不朽的 ACKD1;byte[] datasD1 dataMsg.getBytes();DatagramPacket datagramPacketD1 new DatagramPacket(datasD1, 0,datasD1.length, new InetSocketAddress(localhost,8888));int maxRetries 3; // 最大重试次数int retryCount 0; // 当前重试次数boolean success false; // 是否成功标志while (!success retryCount maxRetries) {try {// 设置超时时间datagramSocket.setSoTimeout(50000);// 发送数据datagramSocket.send(datagramPacket);// 接收响应byte[] buffer new byte[1024];DatagramPacket responsePacket new DatagramPacket(buffer, buffer.length);datagramSocket.receive(responsePacket);// 处理响应String response new String(responsePacket.getData(), 0, responsePacket.getLength());System.out.println(接收到响应 response);// 设置成功标志success true;} catch (java.net.SocketTimeoutException e) {// 超时后重新发送数据retryCount;System.out.println(超时进行第 retryCount 次重试);} catch (IOException e) {// 处理其他异常e.printStackTrace();}}if (!success) {System.out.println(重试次数超过最大限制操作失败);}
客户端发送数据到服务端
注意在tcp三次握手后数据段的传输也需要添加ACK和Seq如前文所述。这里为了便于实现在传回数据时只写了数据返回 “收到消息” 是不符合规定的需要修改。 System.out.println();System.out.println(开始接收数据段...);byte[] bytes1 new byte[1024];DatagramPacket datagramPacketD1 new DatagramPacket(bytes1, bytes1.length);datagramSocket.receive(datagramPacketD1);String receiveMsg new String(datagramPacketD1.getData(), 0, datagramPacketD1.getLength());System.out.println(接收到的数据段为: receiveMsg);String[] split receiveMsg.split( );String SeqD1 split[0];System.out.println();System.out.println(数据消息确认返回);String replyMsg 收到消息;clientMsg.sendMsg(replyMsg, datagramSocket);