简单应用UDP模拟TCP的项目实现

这篇具有很好参考价值的文章主要介绍了简单应用UDP模拟TCP的项目实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

UDP模拟TCP的项目实现报告

1. 引言

在网络协议中,传输控制协议 (TCP) 和用户数据报协议 (UDP)是两种代表性的设计。UDP是一种简洁、无连接的协议,提供了一种更快速、轻量的通信方式。而TCP是一种可靠、面向连接的协议,确保了数据传输的稳定性,TCP适用于网页浏览、文件传输和电子邮件等,UDP简单高效,适用于对传输延迟要求较高、可容忍一些数据丢失的应用场景,如DNS、SNMP,广播连接等。本文实现了UDP模拟TCP,旨在结合TCP的优点,提高UDP传输的稳定性。

简单应用UDP模拟TCP的项目实现,udp,tcp/ip,网络协议

2.理论基础

2.1 TCP特性概述

传输控制协议TCP更加可靠,TCP确保数据包按顺序到达接收方,且不丢失,使用确认和重传机制来实现可靠性。它具有流量控制机制,以防止发送方过载接收方,以及拥塞控制机制,以监测和缓解网络拥塞。TCP是面向连接的,需要进行连接的建立和断开,同时使用数据校验来保证数据的完整性。

2.2 UDP特性概述

用户数据报协议(UDP)更加简单。UDP不提供可靠的数据传输,数据包可能丢失、重复或乱序到达,没有确认和重传机制。由于无连接和简单的特性,UDP具有较低的传输延迟,适用于实时应用。它支持广播和多播,允许将数据包同时发送给多个接收方。UDP将数据分割成数据报进行传输,每个数据报具有固定大小,但不提供数据校验机制。

2.3 UDP模拟TCP的前景

在游戏领域,将TCP的可靠性模拟到低延迟的UDP协议中,可以提高用户体验,UDP模拟TCP的机制可以提供必要的数据传输可靠性,同时保持低延迟的特性。

3. TCP协议机制

3.1 三次握手

首先,客户端发送一个带有同步序列号的数据包到服务器,请求连接开始。随后,服务器响应客户端的请求,发送一个同时包含同步确认序列号的数据包,回应客户端。客户端再发送一个带有确认序列号的数据包给服务器,建立连接过程。

3.2 超时重传

握手过程中,发送方启动计时器以监控ACK的接收,如果在设定的超时时间内未收到ACK,将触发数据包的重传。在连续超时的情况下,TCP通过逐步增加超时时间间隔来适应网络拥塞,并实施快速重传机制,同时根据网络的稳定性和动态性调整超时时间。

3.3 流量控制

在TCP通信中,接收方会告知发送方自己的可用接收窗口大小,表示能够接受的未确认数据的字节数。发送方根据接收窗口大小来控制发送速率,确保不会发送超过接收方能够处理的数据量,以避免数据丢失或缓冲区溢出的情况发生。

窗口大小可以动态调整,根据网络条件和接收方的处理速度进行适时的调整,提高数据传输的可靠性和效率。

3.4 拥塞控制

当网络中出现拥塞时,TCP采取一系列措施来避免过多的数据流量导致网络性能下降或崩溃。这包括减小发送速率,通过调整拥塞窗口大小来限制数据包的发送数量,并使用慢启动、拥塞避免和快速恢复等算法来逐步测试和调整网络的容量。

3.5 乱序数据处理

接收方接收到的数据包的序列号若不按顺序排列,它将把这些数据包放入一个缓存区中,等待后续的数据包到达,以便进行正确的排序。同时,接收方会要求重传,检测到丢失的数据包,再将缓存区的乱序数据包排序再交付给应用程序。

4. UDP模拟实现

要实现UDP实现TCP的要点,需要保证顺序性、可靠性、控制传输速率,包括但不限于以下内容,其中大部分要点都已实现:

  1. 传输机制:

    • 三次握手四次挥手
    • 引入序列号
  2. 重传机制:

    • 超时重传
    • 自适应RTO、动态RTT估计RTO
    • 快速重传
  3. 校验机制:

    • 设置缓冲区储存:乱序、丢失、损坏数据包
    • 检测和请求重传:丢失或者损坏数据包
  4. 流量控制:

    • 发送滑动窗口大小
    • 控制发送速率匹配窗口大小
  5. 拥塞控制:

    • 网络拥塞时减小窗口大小

    • 模拟慢启动、拥塞避免、快速恢复来动态调整窗口大小

4.1 UDP模拟TCP的传输机制

模拟三次握手四次挥手

在握手过程中,双方各自初始化序列号,这对于后续处理至关重要,能保证数据包的顺序,也能检测丢失、重复的数据,也方便流量控制和拥塞控制。在UDP中引入序列号,使得每个UDP数据包都可以被追踪。

客户端发送数据时附带序列号
data = f"{client_seq + seq}:{message}:{checksum(message)}"

握手步骤 握手过程
SYN 客户端发送一个包含“SYN”的数据包以及选择一个“初始序列号ISN”到服务器,以开始建立连接
SYN-ACK 若服务器收到SYN后,发送一个包含“SYN-ACK”标记的数据包和“客户端的ISN确认号”作为响应。
ACK 客户端收到“SYN-ACK“后,发送一个“ACK”标记和“服务器的ISN确认号”的数据包。

我通过UDP协议模拟了TCP的三次握手和四次挥手机制。在三次握手中,客户端首先发送一个带有序列号的SYN包,服务器回应一个SYN-ACK包,最后客户端发送一个ACK包来确认连接。客户端和服务器分别发送FIN和ACK包以关闭连接,四次挥手使得连接终止。

服务器三次握手四次挥手代码示例:

第一步:接收客户端的SYN
syn_data, client_address = server_socket.recvfrom(1024)
if syn_data.decode().startswith('SYN'):
第二步:发送SYN-ACK给客户端
server_socket.sendto(f'SYN-ACK:{server_seq}'.encode(), client_address)
第三步:等待客户端的ACK
ack_data, client_address = server_socket.recvfrom(1024)

客户端向服务器发送FIN
client_socket.sendto(f"FIN:{client_seq + len(messages)}".encode(), (ip, port))
等待服务器的FIN-ACK
fin_ack, _ = client_socket.recvfrom(1024)

4.2 UDP模拟TCP的超时重传

UDP协议发送数据包时开启超时计时器,到接收到对应ACK的时间,发送方可以测量往返时间RTT,监控ACK的接收情况。设置一个超时时间,在预定超时时间内未收到ACK时,触发数据包的重传。

client_socket.settimeout(estimated_rtt)# 设置超时时间

client_socket.sendto(data.encode(), (ip, port))# 超时后重传

时间估计优化

这里我使用了RTT动态估计RTO,降低了延迟对超时时间的影响。

RTT估计RTO函数示例:
def calculate_rto(sample_rtt, estimated_rtt, dev_rtt):
alpha = 0.125
beta = 0.25
estimated_rtt = (1 - alpha) * estimated_rtt + alpha * sample_rtt
dev_rtt = (1 - beta) * dev_rtt + beta * abs(sample_rtt - estimated_rtt)
return estimated_rtt + 4 * dev_rtt

当网络稳定时,使用预设的固定值,固定延迟的值可以在连接建立时测量几次RTT,然后取平均值作为固定延迟估计。

在不稳定的网络环境中,使用加权平均方法对RTT进行平滑处理,使用指数加权移动平均来减少暂时性网络波动的影响。

快速重传优化

快速重传机制,如果接收方收到一个乱序的数据包,它可以立即发送一个对最后按顺序接收的数据包的ACK。如果发送方收到对同一数据包的三个冗余ACK,它可能会立即重传该数据包,而不是等待超时。

#当重复数等于三时触发快速重传

if duplicate_acks == 3:

连续超时优化

指数退避机制,在连续的超时情况下,UDP可以通过增加超时时间间隔来模拟TCP的指数退避策略。在连续超时的情况下,超时时间间隔可以每次翻倍,这称为。它有助于适应网络拥塞状况,避免在网络已经拥塞的情况下过多地发送数据。

同时等待时间不会无限增大,最终的超时时间应该包括一个额外的边际值,以应对不可预见的延迟波动。

4.3 UDP模拟TCP的缓冲区

检测和请求重传

在服务器端,我设置了一个缓冲区来处理乱序、丢失或损坏的数据包,并利用简单的校验函数来判断,若检测到数据包损坏或丢失时忽略该包,等待重传。

检测与忽略代码示例:
buffer = {} # 缓存乱序到达的数据包
while expected_seq in buffer:
buffered_data = buffer.pop(expected_seq)
if checksum(data) != chksum:
print(f"Packet {packet_seq} corrupted. Ignored.")

4.4 UDP模拟TCP的滑动窗口

UDP协议中接收方通过发送窗口大小信息告知其当前能够接收的数据量,发送方据此调整发送速率,匹配接收方的接受能力,以实现流量控制。

显式窗口大小反馈

UDP缺乏内部的流量控制机制,需要设置一种显式的反馈窗口,告知发送方当前的接受能力。

# 更新当前窗口大小

current_window_size = min(congestion_window, MAX_WINDOW_SIZE)

控制发送速率

通过动态调整窗口大小来控制数据的发送速率,窗口大小应该与网络条件和缓存区情况有关,若缓冲区满或者延迟高时,应减小窗口大小

4.5 UDP模拟TCP的拥塞窗口

通过调整数据发送速率响应网络拥塞情况,模拟TCP的拥塞控制。在丢包时减少发送速率,在无丢包时逐渐增加。同时模仿TCP的慢启动、拥塞避免、快速恢复的策略,通过调整拥塞窗口大小来控制数据发送速率。

拥塞控制状态转换代码示例:
# 拥塞控制状态调整 if congestion_state == "slow_start": congestion_window += 1 if congestion_window >= THRESHOLD: congestion_state = "congestion_avoidance" elif congestion_state == "congestion_avoidance": congestion_window += 1 / congestion_window elif congestion_state == "fast_recovery": congestion_window = THRESHOLD / 2 congestion_state = "slow_start"

快速恢复代码示例:
# 进入快速恢复状态 if duplicate_acks == 3: congestion_state = "fast_recovery" THRESHOLD = current_window_size // 2 current_window_size = THRESHOLD + 3

5. 结果分析

这里我实现了三次握手和四次挥手的连接机制、超时重传、动态RTT估计、快速重传、流量控制、拥塞控制以及缓冲区管理等TCP特性。通过模拟TCP的机制,在保持UDP低延迟特性的同时,显著增强了传输过程的可靠性和稳定性。

6. 附录

6.1 实验环境与工具

运行环境:python 3.9.10

导入库:socket

6.2 完整代码

运行方式:打开两个命令行,分别运行Server.py和Client.py。文章来源地址https://www.toymoban.com/news/detail-849420.html

Server.py
# 服务器

import socket
import time
import random

# 生成随机的初始序列号
def generate_initial_seq():
    return random.randint(0, 10000)

# 简单校验和函数
def checksum(data):
    return sum(data.encode()) % 256


def udp_server(ip, port):
    INITIAL_WINDOW_SIZE = 1  # 滑动窗口的初始大小
    MAX_WINDOW_SIZE = 1000  # 滑动窗口的最大大小
    THRESHOLD = 64  # 初始拥塞窗口阈值
    congestion_window = 1  # 初始拥塞窗口大小
    duplicate_acks = 0 # 用于跟踪重复ACK的计数器
    last_ack_received = -1

    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server_socket.bind((ip, port))
    print("UDP Server listening on port:", port)

    while True:
        # 三次握手过程
        # 第一步:接收客户端的SYN
        syn_data, client_address = server_socket.recvfrom(1024)
        if syn_data.decode().startswith('SYN'):
            server_seq = generate_initial_seq()  # 随机生成服务器端的初始序列号
            print(f"SYN received from client. Sending SYN-ACK with ISN: {server_seq}...")
            # 第二步:发送SYN-ACK给客户端
            server_socket.sendto(f'SYN-ACK:{server_seq}'.encode(), client_address)
            # 第三步:等待客户端的ACK,建立连接
            ack_data, client_address = server_socket.recvfrom(1024)
            if ack_data.decode().startswith('ACK'):
                print("ACK received from client. Connection established.")
                server_seq += 1  # 服务器端的序列号增加

                # 数据接收、乱序处理和确认发送
                buffer = {}  # 缓存乱序到达的数据包
                expected_seq = server_seq + 1  # 期望接收的序列号
                current_window_size = INITIAL_WINDOW_SIZE  # 当前窗口大小
                duplicate_acks = 0  # 重复ACK计数
                congestion_state = "slow_start"  # 拥塞状态:slow_start, congestion_avoidance, fast_recovery

                while True:
                    packet_data, client_address = server_socket.recvfrom(1024)
                    if packet_data.decode().startswith('FIN'):
                        print("FIN received from client. Sending FIN-ACK...")
                        server_socket.sendto(f'FIN-ACK'.encode(), client_address)
                          # 最后的ACK确认
                        last_ack_data, client_address = server_socket.recvfrom(1024)
                        if last_ack_data.decode().startswith('ACK'):
                            print("Final ACK received. Connection terminated.")
                            break  # 跳出接收循环

                    packet_seq,data, chksum = packet_data.decode().split(':', 2)
                    packet_seq = int(packet_seq)
                    chksum = int(chksum)
                    # 检查校验
                    if checksum(data) != chksum:
                        print(f"Packet {packet_seq} corrupted. Ignored.")
                        continue
                    
                    # 正确顺序的数据包
                    if packet_seq == expected_seq:
                        print(f"Received correct packet {packet_seq}: {data}")
                        expected_seq += 1 # 更新期望的序列号
                        duplicate_acks = 0 # 重置重复ACK计数
                        # 发送ACK
                        server_socket.sendto(f"ACK:{expected_seq}".encode(), client_address)

                        # 处理缓存中的数据包
                        while expected_seq in buffer:
                            buffered_data = buffer.pop(expected_seq)
                            print(f"Received buffered packet {expected_seq}: {buffered_data}")
                            expected_seq += 1
                            server_socket.sendto(f"ACK:{expected_seq}".encode(), client_address)

                    # 乱序到达的数据包
                    elif packet_seq > expected_seq:
                        print(f"Received out-of-order packet {packet_seq}. Buffering...")
                        buffer[packet_seq] = data
                        server_socket.sendto(f"ACK:{expected_seq - 1}".encode(), client_address)  # 发送重复ACK

                        # 若ACK不同,增加计数
                        if expected_seq - 1 == last_ack_received:
                            duplicate_acks += 1
                        
                        if duplicate_acks == 3:
                            # 触发快速重传机制
                            if expected_seq in buffer:
                                data_to_resend = buffer[expected_seq]
                                server_socket.sendto(f"{expected_seq}:{data_to_resend}:{checksum(data_to_resend)}".encode(), client_address)
                                print(f"Resent packet {expected_seq}: {data_to_resend}")
                            else:
                                print(f"Packet {expected_seq} not found in buffer for retransmission.")
                            duplicate_acks = 0

                            # 进入快速恢复状态
                            congestion_state = "fast_recovery"
                            THRESHOLD = current_window_size // 2
                            current_window_size = THRESHOLD + 3
                        else:
                            # 收到的是新的ACK,重置重复ACK计数器
                            duplicate_acks = 1
                        last_ack_received = expected_seq - 1

                    # 拥塞控制:根据状态调整窗口大小
                    if congestion_state == "slow_start":
                        congestion_window += 1
                        if current_window_size >= THRESHOLD:
                            congestion_state = "congestion_avoidance"

                    elif congestion_state == "congestion_avoidance":
                        congestion_window += 1 / congestion_window

                    elif congestion_state == "fast_recovery":
                        congestion_window = THRESHOLD / 2
                        congestion_state = "slow_start"
                        
                     # 更新当前窗口大小
                    current_window_size = min(congestion_window, MAX_WINDOW_SIZE)
                            
            # 四次挥手过程
            print("FIN received from client. Sending FIN-ACK...")
            server_socket.sendto(f'FIN-ACK'.encode(), client_address)

            # 最后的ACK确认
            last_ack_data, client_address = server_socket.recvfrom(1024)
            if last_ack_data.decode().startswith('ACK'):
                print("Final ACK received. Connection terminated.")

        server_socket.close()


# 获取服务器的主机名和端口号
# host = socket.gethostname()
host = '127.0.0.1'
port = 8888
# 启动服务器
udp_server(host, port)

Client.py
# 客户端

import socket
import time
import random

# 生成随机的初始序列号
def generate_initial_seq():
    return random.randint(0, 10000)

# 简单校验函数
def checksum(data):
    return sum(data.encode()) % 256

# 计算RTO
def calculate_rto(sample_rtt, estimated_rtt, dev_rtt):
    alpha = 0.125
    beta = 0.25
    estimated_rtt = (1 - alpha) * estimated_rtt + alpha * sample_rtt
    dev_rtt = (1 - beta) * dev_rtt + beta * abs(sample_rtt - estimated_rtt)
    return estimated_rtt + 4 * dev_rtt


def udp_client(ip, port, messages):
    INITIAL_WINDOW_SIZE = 1  # 滑动窗口的初始大小
    MAX_WINDOW_SIZE = 1000  # 滑动窗口的最大大小
    MAX_TIMEOUT_RETRIES = 5 # 最大超时重传次数

    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    client_seq = generate_initial_seq()  # 客户端的序列号
    # 三次握手过程
    # 第一步:发送SYN到服务器
    client_socket.sendto(f'SYN:{client_seq}'.encode(), (ip, port))
    print(f"SYN:{client_seq} sent to server.")

    # 第二步:等待服务器的SYN-ACK
    try:
        client_socket.settimeout(2.0) # 设置超时时间 
        syn_ack, _ = client_socket.recvfrom(1024)
        server_seq = int(syn_ack.decode().split(':')[1])
        if syn_ack.decode().startswith('SYN-ACK') and server_seq == client_seq + 1:
            print("SYN-ACK received from server. Sending ACK...")
            # 第三步:发送ACK到服务器
            client_seq += 1
        client_socket.sendto(f'ACK:{client_seq}'.encode(), (ip, port))
        print(f"ACK:{client_seq} sent to server. Connection established.")

        # 初始化RTO计算参数
        estimated_rtt = 0
        dev_rtt = 0

        # 数据发送和确认接收
        window_size = INITIAL_WINDOW_SIZE # 初始化窗口大小
        for seq, message in enumerate(messages):
            data = f"{client_seq + seq}:{message}:{checksum(message)}"
            client_socket.sendto(data.encode(), (ip, port))
            print(f"Sent: {data}")

            timeout_count = 0  # 超时计数器

            while True:
                try:
                    start_time = time.time()# 等待确认
                    ack_data, _ = client_socket.recvfrom(1024)
                    end_time = time.time()
                    sample_rtt = end_time - start_time

                    if ack_data.decode().startswith("ACK"):
                        ack_seq = int(ack_data.decode().split(':')[1])
                        if ack_seq >= client_seq + seq:
                            print(f"ACK received for packet {client_seq + seq}")
                            # 更新RTO
                            estimated_rtt = calculate_rto(sample_rtt, estimated_rtt, dev_rtt)
                            client_socket.settimeout(estimated_rtt)
                            break
                    elif ack_data.decode().startswith("WINDOW"):
                        window_size = int(ack_data.decode().split(':')[1])
                        congestion_window = min(window_size, congestion_window + 1)
                        print(f"Updated window size: {window_size}")
                

                except socket.timeout:
                    print(f"Timeout. Resending packet {client_seq + seq}.")
                    # 重传
                    client_socket.sendto(data.encode(), (ip, port))
                    timeout_count += 1
                    if timeout_count > MAX_TIMEOUT_RETRIES:
                        print("Max retries exceeded. Connection closed.")
                        return
                # 等待一段时间或检查窗口大小,然后发送下一个数据包
            time.sleep(max(0, 1 - window_size / MAX_WINDOW_SIZE))

        # 四次挥手过程
        # 发送FIN
        client_socket.sendto(f"FIN:{client_seq + len(messages)}".encode(), (ip, port))
        print(f"FIN sent to server.")

        # 等待服务器的FIN-ACK
        try:
            fin_ack, _ = client_socket.recvfrom(1024)
            if fin_ack.decode().startswith("FIN-ACK"):
                print("FIN-ACK received from server.")
                # 发送ACK
                client_socket.sendto(f"ACK:{client_seq + len(messages) + 1}".encode(), (ip, port))
                print("ACK sent to server. Connection terminating.")
                # 等待服务器的最后ACK
                try:
                    final_ack, _ = client_socket.recvfrom(1024)
                    if final_ack.decode().startswith("ACK"):
                        print("Final ACK received from server. Connection terminated.")
                except socket.timeout:
                    print("Final ACK from server not received. Connection forcefully closed.")
        except socket.timeout:
            print("Server did not respond to FIN. Connection forcefully closed.")

    except socket.timeout:
        print("Connection timeout. Server did not respond.")

    client_socket.close()



# 客户端的主机名和端口号
# host = socket.gethostname()
host = '127.0.0.1'
port = 8888
messages = ["Test1", "Test2222", "Test3333333333"]
udp_client(host, port, messages)

到了这里,关于简单应用UDP模拟TCP的项目实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python模拟TCP与UDP发送数据包

    在项目测试中需要发送指定内容的数据包到目标位置,并且需要发送的数量极大,真实环境无法满足测试需求,但是以Python为基础语言,结合Socket和Scrapy便可以支撑测试,其中Socket可以支持大量数据包由本机发送给目标机,scapy则可以模拟发生源IP发送数据包给目标及,但每秒

    2024年02月05日
    浏览(43)
  • TCP/IP、UDP和TELNET

           TCP/IP是一个Protocol Stack,包括TCP、IP、UDP、ICMP、RIP、TELNET、FTP、SMTP、ARP等许多协议。        最早发源于1969年美国国防部(缩写为DoD)的因特网的前身ARPA网络项目,1983年1月1日,TCP/IP取代了旧的网络控制协议NCP,成为今天的互联网和局域网的基石和标准,由互联网工

    2024年01月25日
    浏览(47)
  • 简单理解TCP,UDP,HTTP

    我们都知道TCP、UDP、HTTP内部有很复杂的过程,很多人没办法理解的那么深,只想知道这是个什么鬼。 TCP/IP是个协议组,可分为三个层次:网络层、传输层和应用层。 在网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。 在传输层中有TCP协议与UDP协议。 在应用层有FTP、

    2024年02月16日
    浏览(36)
  • 网络编程——TCP/IP协议族(IP协议、TCP协议和UDP协议……)

    1、IP协议简介 IP协议又称 网际协议 特指为实现在一个相互连接的网络系统上从源地址到目的地传输数据包(互联网数据包)所提供必要功能的协议,是网络层中的协议。 2、特点 不可靠 :它不能保证IP数据包能成功地到达它的目的地,仅提供尽力而为的传输服务 无连接 :IP 并不

    2024年02月13日
    浏览(75)
  • HTTP/UDP/TCP/IP网络协议

    OSI模型定义了网络互连的七层框架(物理层、数据链路层、网络层、传输层、会话层、表示层、应用层),每一层实现各自的功能和协议,并完成与相邻层的接口通信。OSI模型各层的通信协议,大致举例如下表所示: 层次 常见协议 应用层 HTTP、SMTP、SNMP、FTP、Telnet、SIP、SS

    2024年04月11日
    浏览(43)
  • TCP、UDP、IP、RTP头长度

    各种协议的数据包头长度如下: UDP 头(8 字节) 源端口(2 字节) 目标端口(2 字节) UDP 数据包长度(2 字节) 校验和(2 字节) RTP 头(12 字节或者24字节) 版本号(2位) 填充位(1位) 扩展位(1位) CSRC计数器(4位) 标记位(1位) 负载类型(7位) 序列号(16位) 时

    2024年02月11日
    浏览(45)
  • TCP/IP UDP广播无法发送或接收

    在看《TCP/IP 网络编程》这本书的时候,看到广播那一节,跟着书上写代码,怎么写都不行,广播就是没法发送/接收,发送端一直在发送数据,接收端就是没有反应。 对了好几遍源码,没有问题。实在是愁人。 最后查了很多资料,确定是网卡的问题。 现在的计算机都是多网

    2024年02月04日
    浏览(51)
  • TCP/IP协议族之TCP、UDP协议详解(小白也能看懂)

            在进行网络编程之前,我们必须要对网络通信的基础知识有个大概的框架,TCP/IP协议族涉及到多种网络协议,一般说TCP/IP协议,它不是指某一个具体的网络协议,而是一个协议族。本篇章主要针对IP协议、TCP和UDP协议记录总结。 OSI七层参考模型是国际标准化组织(

    2024年02月02日
    浏览(47)
  • IP、ICMP、UDP、TCP 校验和算法分享

    以前看计算机网络相关的书,每次看到IP或者UDP报头校验和时,都一瞥而过,以为相当简单,不就是16bit数据的相加吗。最近在研究《TCP/IP详解 卷1:协议》这本书,看到校验和是 16bit字的二进制反码和 (晕,以前都没注意原来是反码和,看来以前看书不仔细啊!罪过,罪过

    2024年02月06日
    浏览(43)
  • TCP、UDP、IP以及ensp基本配置

    目录 一、TCP报文段 二、UDP报文段 三、IP报文段 四、ensp基本配置​          源端口号: 表示发数据那个进程的端口号。          目的端口号: 表示收数据那个进程的端口号。          校验和: 验证数据的传输是否是正确的。          选项 :扩展Tcp功能时

    2024年02月02日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包