网络编程中的TCP和UDP

news2024/9/22 14:22:15

 

什么是TCP协议

TCP( Transmission control protocol )即传输控制协议,是一种面向连接、可靠的数据传输协议,它是为了在不可靠的互联网上提供可靠的端到端字节流而专门设计的一个传输协议。

  • 面向连接 :数据传输之前客户端和服务器端必须建立连接

  • 可靠的 :数据传输是有序的 要对数据进行校验

 

TCP三次握手

为了保证客户端和服务器端的可靠连接,TCP建立连接时必须要进行三次会话,也叫TCP三次握手,进行三次握手的目的是为了确认双方的接收能力和发送能力是否正常。

  1. 第一次握手(呼叫请求)
    • 你(客户端):想要和某人通话,于是你拿起电话,拨打对方的号码。这个动作相当于TCP中的SYN(同步序列编号)包发送。你告诉对方(服务器):“嘿,我在这里,我想和你建立通话。”
  2. 第二次握手(接听确认)
    • 对方(服务器):听到电话铃声后,接起电话,并对你的呼叫做出响应。这相当于TCP中的SYN-ACK(同步确认)包发送。对方(服务器)说:“我听到了,我也在这里,我们可以开始通话了。”同时,对方(服务器)也确认了你的存在,并准备好接下来的通信。
  3. 第三次握手(确认接听)
    • 你(客户端):在听到对方的接听确认后,你回应一个确认信号,告诉对方你已经准备好开始通话了。这相当于TCP中的ACK(确认)包发送。你说:“好的,我已经准备好了,我们可以开始通话了。”

 

  • 第一次握手 TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这是报文首部中的同部位SYN=1,同时选择一个初始序列号 seq=x ,此时,TCP客户端进程进入了 SYN-SENT 同步已发送状态
  • 第二次握手 TCP服务器收到请求报文后,如果同意连接,则会向客户端发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号 seq=y,此时,TCP服务器进程进入了 SYN-RCVD 同步收到状态.
  • 第三次握手 TCP客户端收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED已建立连接状态 触发三次握手

三次握手主要作用:防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误

第一次握手: 客户端向服务器端发送报文 证明客户端的发送能力正常 第二次握手:服务器端接收到报文并向客户端发送报文 证明服务器端的接收能力、发送能力正常 第三次握手:客户端向服务器发送报文 证明客户端的接收能力正常


TCP四次挥手

建立TCP连接需要三次握手,终止TCP连接需要四次挥手。

张三:好的,那我先走了

李四:好的,那你走吧

李四:那我也走了?

张三:好的,你走吧  

 

Socket的定义

Socket的英文原义是“孔”或“插座”,网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

建立网络通信连接至少要一对端口号(socket),socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口。

Python 官方关于 Socket 的函数 socket — Low-level networking interface — Python 3.12.4 documentation

Socket的类型  

  • TCP发送数据时,已建立好TCP连接,所以不需要指定地址。UDP是面向无连接的, 每次发送要指定是发给谁。

  • 服务端与客户端不能直接发送列表,元组,字典。需要字节化(data)。

服务端socket函数:

客户端Socket函数

 

共有的函数 :

SOCKET函数描述
s.recv(bufsize[,flag])接受TCP,UDP套接字的数据。数据以字符串形式返回,bufsize指定要接收的最大数据量。
s.send(string[,flag])发送TCP,UDP数据。
s.sendall(string[,flag])完整发送TCP数据。
s.recvfrom(bufsize[.flag])接受UDP套接字的数据。与recv()类似,但返回值是(data,address)。
s.sendto(string[,flag],address)发送UDP数据。将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。
s.close()关闭套接字。
s.getpeername()返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。
s.getsockname()返回套接字自己的地址。
s.setsockopt(level,optname,value)设置给定套接字选项的值。
s.getsockopt(level,optname[.buflen])设置给定套接字选项的值。
s.settimeout(timeout)设置套接字操作的超时期
s.gettimeout()返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。
s.fileno()返回套接字的文件描述符。
s.setblocking(flag)如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。
s.makefile()创建一个与该套接字相关连的文件

TCP实现一对一的简单聊天

服务端代码:

from socket import *


tcp_server = socket(AF_INET, SOCK_STREAM)

# 绑定本地信息,TCP服务器程序监听所有网络接口上的88888端口
host_port = ('', 88888)  
tcp_server.bind(host_port)

# 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了
tcp_server.listen(5)

while True:


    newSocket, host_port = tcp_server.accept()

    while True:

        # 最大接收1024个字节
        recvData = newSocket.recv(1024)

        if len(recvData) > 0:
            print('recv:', recvData)
        else:
            break

        sendData = input("send:")
        newSocket.send(sendData.encode('utf8'))


    newSocket.close()

tcp_server.close()

客户端代码:

from socket import *


tcp_client = socket(AF_INET, SOCK_STREAM)

# 链接服务器
host_port = ('127.0.0.1', 88888)
tcp_client.connect(host_port)

while True:


    sendData = input("send:")

    if len(sendData) > 0:
        tcp_client.send(sendData.encode('utf8'))
    else:
        break

    # 最大接收1024个字节
    recvData = tcp_client.recv(1024)
    print('recv:', recvData.decode('uft8'))

tcp_client.close()

UDP

UDP ---(User Datagram Protocol) 用户数据报协议,是一个无连接的简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,没有超时重发等机制,所以传输速度很快。

UDP是一种面向无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。

UDP特点:

UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。 UDP传输数据时有大小限制,每个被传输的数据报必须限定在64KB之内。 UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。

【适用情况】 UDP是面向消息的协议,通信时不需要建立连接,数据的传输自然是不可靠的,UDP一般用于多点通信和实时的数据业务,比如

  • 语音广播

  • 视频

  • QQ

  • TFTP(简单文件传送)

  • 大型网络游戏

相比较于TCP注重速度流畅

UDP简单案例

服务端代码

import socket

sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定 IP 和端口号
sk.bind(('127.0.0.1', 88888))
while True:

  msg, addr = sk.recvfrom(1024)

  print('来自[%s:%s]的消息: %s' % (addr[0], addr[1], msg.decode('utf-8')))
 

  inp = input('>>>')

  sk.sendto(inp.encode('utf-8'), addr)
 
sk.close()

 客户端代码:

import socket
 

sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
addr = ('127.0.0.1', 88888)
while True:

  msg = input('>>>')
  sk.sendto(msg.encode('utf-8'), addr)
  msg_recv, addr = sk.recvfrom(1024)
  print(msg_recv.decode('utf-8'))
 
sk.close()

实现简单TFTP(基于UDP协议) 

实现一个简单的TFTP(Trivial File Transfer Protocol)服务器和客户端基于UDP协议是一个有趣的小练习。TFTP是一个简单的文件传输协议,它使用UDP协议,并且通常用于小文件的传输。

我们值实现最基本的功能:从服务器读取文件并发送到客户端。 

TFTP 服务器:

import socket  
import struct  
  
def handle_client(sock, filename):  
    # 假设文件存在且小于65535字节  
    try:  
        with open(filename, 'rb') as file:  
            data = file.read(512)  # TFTP块大小为512字节  
            block_number = 1  
            while data:  
                # 发送DATA包:block_number + data  
                block_info = struct.pack('!H', block_number)  # 网络字节序的短整型  
                sock.sendto(block_info + data, client_address)  
                  
                # 等待ACK  
                ack_data, _ = sock.recvfrom(2)  # 只接收block number  
                ack_block_number = struct.unpack('!H', ack_data)[0]  
                  
                if ack_block_number != block_number:  
                    print("Incorrect block number in ACK")  
                    break  
                  
                block_number += 1  
                data = file.read(512)  
    except FileNotFoundError:  
        # 发送ERROR包  
        error_code = 1  # File not found  
        error_msg = struct.pack('!HH', error_code, 0)  # TFTP错误消息格式  
        sock.sendto(error_msg, client_address)  
  
def start_tftp_server(port, root_dir):  
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  
    server_socket.bind(('0.0.0.0', port))  
  
    print(f"TFTP server listening on port {port}...")  
  
    while True:  
        data, client_address = server_socket.recvfrom(1024)  # 接收RRQ或WRQ请求  
        # 这里简化处理,只处理RRQ  
        if data.startswith(b'\x00\x01'):  # RRQ的opcode  
            filename = data[2:].decode().split(b'\x00')[0]  
            filepath = f"{root_dir}/{filename}"  
            handle_client(server_socket, filepath)  
  
if __name__ == "__main__":  
    start_tftp_server(69, './files') 

TFTP 客户端:

import socket  
import struct  
  
def request_file(server_ip, server_port, filename):  
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  
  
    # 发送RRQ请求  
    rrq = b'\x00\x01' + filename.encode() + b'\x00' + b'octet' + b'\x00'  # mode为octet  
    client_socket.sendto(rrq, (server_ip, server_port))  
  
    block_number = 0  
    data = b''  
  
    while True:  
        # 接收DATA包  
        data_packet, _ = client_socket.recvfrom(514)  # 512字节数据 + 2字节块号  
        block_number = struct.unpack('!H', data_packet[:2])[0]  
        if block_number == 0:  # 假设块号为0表示文件结束或错误  
            break  
  
        data += data_packet[2:]  
  
        # 发送ACK  
        ack = struct.pack('!H', block_number)  
        client_socket.sendto(ack, (server_ip, server_port))  
  
    client_socket.close()  
  
    # 处理接收到的数据(例如,写入文件)  
    with open(filename, 'wb') as file:  
        file.write(data)  
  
if __name__ == "__main__":  
    request_file('127.0.0.1', 69)
    file_name = 'example.txt'  
    request_file(server_addr, 69, file_name)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1938695.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能与语音识别:技术进步与应用前景

引言 人工智能(AI)作为当今科技进步的核心驱动力,正在各个领域展现其变革力量。其中,语音识别技术作为人工智能的重要应用之一,已经深入到我们的日常生活和工作中。从智能助手如Siri、Google Assistant,到智…

最新版kubeadm搭建k8s(已成功搭建)

kubeadm搭建k8s(已成功搭建) 环境配置 主节点 k8s-master:4核8G、40GB硬盘、CentOS7.9(内网IP:10.16.64.67) 从节点 k8s-node1: 4核8G、40GB硬盘、CentOS7.9(内网IP:10…

n5.Nginx 常见模块

Nginx 常见模块 4.1 Nginx 四层访问控制4.2 Nginx 账户认证功能4.3 自定义错误页面4.4 自定义错误日志4.5 检测文件是否存在4.6 长连接配置4.7 作为下载服务器配置4.8 作为上传服务器4.9 限流限速4.10 Nginx 状态页 4.1 Nginx 四层访问控制 访问控制基于模块ngx_http_access_m…

【一刷《剑指Offer》】面试题 37:两个链表的第一个公共结点

力扣对应题目链接:160. 相交链表 - 力扣(LeetCode) 牛客对应题目链接:两个链表的第一个公共结点_牛客题霸_牛客网 (nowcoder.com) 核心考点 :单链表理解,临界条件判定。 一、《剑指Offer》对应内容 二、分…

Python酷库之旅-第三方库Pandas(036)

目录 一、用法精讲 111、pandas.Series.item方法 111-1、语法 111-2、参数 111-3、功能 111-4、返回值 111-5、说明 111-6、用法 111-6-1、数据准备 111-6-2、代码示例 111-6-3、结果输出 112、pandas.Series.xs方法 112-1、语法 112-2、参数 112-3、功能 112-…

快速了解死锁及如何解决死锁问题

目录 什么是死锁? 死锁代码示例 产生死锁的条件: 死锁的危害: 如何解决死锁问题? 1、预防死锁(破坏上述4个产生死锁的条件): 2、银行家算法 3、死锁的检测、解除 4、采用超时机制 什么…

C语言 ——— 写一个函数,调整 整型数组 中 奇数偶数的顺序

目录 题目要求 代码实现 题目要求 创建一个整型数组 自定义函数实现:调整该数组中数字的顺序,使得数组中所有的奇数位于数组的前半部分,数组中所有的偶数位于数组的后半部分 举例: 输入的整型数组为:[234,24,45,…

计算机网络知识点面试总结3

#来自ウルトラマンゼロ(赛罗) 1 数据链路层功能 数据链路层在物理层提供的服务的基础上向网络层提供服务,其最基本的服务是将源自网络层来的数据可靠地传输到相邻节点的目标机网络层,其主要作用是加强物理层传输原始比特流的功能。…

嵌入式面试总结

C语言中struct和union的区别 struct和union都是常见的复合结构。 结构体和联合体虽然都是由多个不同的数据类型成员组成的,但不同之处在于联合体中所有成员共用一块地址空间,即联合体只存放了一个被选中的成员,结构体中所有成员占用空间是累…

nginx基本原理

进程模型 当nginx启动之后,会有一个master进程和多个worker进程。默认是一个worker进程。 master进程的作用:接收来自外界信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程在异常情况下退出后&am…

Golang | Leetcode Golang题解之第242题有效的字母异位词

题目&#xff1a; 题解&#xff1a; func isAnagram(s, t string) bool {if len(s) ! len(t) {return false}cnt : map[rune]int{}for _, ch : range s {cnt[ch]}for _, ch : range t {cnt[ch]--if cnt[ch] < 0 {return false}}return true }

系统架构设计师教程 第3章 信息系统基础知识-3.6 办公自动化系统(OAS)-解读

系统架构设计师教程 第3章 信息系统基础知识-3.6 办公自动化系统&#xff08;OAS&#xff09; 3.6.1 办公自动化系统的概念3.6.1.1 办公活动3.6.1.1 办公自动化的概念 3.6.2 办公自动化系统的功能3.6.2.1 事务处理3.6.2.1.1 单机系统3.6.2.1.2 多机系统 3.6.2.2 信息管理3.6.2.…

科研绘图系列:R语言雨云图(Raincloud plot)

介绍 雨云图(Raincloud plot)是一种数据可视化工具,它结合了多种数据展示方式,旨在提供对数据集的全面了解。雨云图通常包括以下几个部分: 密度图(Density plot):表示数据的分布情况,密度图的曲线可以展示数据在不同数值区间的密度。箱线图(Box plot):显示数据的中…

大模型实战—大模型赋能网络爬虫

大模型赋能网络爬虫 简单来说,网页抓取就是从网站抓取数据和内容,然后将这些数据保存为XML、Excel或SQL格式。除了用于生成潜在客户、监控竞争对手和市场研究外,网页抓取工具还可以用于自动化你的数据收集过程。 借助AI网页抓取工具,可以解决手动或纯基于代码的抓取工具的…

配置kali 的apt命令在线安装包的源为国内源

目录 一、安装VMware Tools 二、配置apt国内源 一、安装VMware Tools 点击安装 VMware Tools 后&#xff0c;会加载一个虚拟光驱&#xff0c;里面包含 VMware Tools 的安装包 鼠标右键单击 VMware Tools 的安装包&#xff0c;点击复制到 点击 主目录&#xff0c;再点击选择…

XILINX芯片解密FPGA/CPLD芯片解密

Xilinx与其技术和制造合作伙伴(TSMC)为FPGA开发了一种高介电层金属闸(HKMG)、高性能、低功耗的28nm工艺技术。这一全新28nm工艺技术是在40nmFPGA工艺技术开发成果的基础上构建的&#xff0c;它推出了新的HKMG技术&#xff0c;可通过较低的功耗来最大程度地发挥可用系统性能。 …

一文彻底搞懂虚拟地址空间

虚拟地址空间&#xff1a;传统的进程管理每个进程都占连续的物理内存空间&#xff0c;如果内存爆满需要将很久没用的但还在内存中的整个进程拷贝到硬盘中&#xff0c;等需要用时重新加载回内存。现代计算机使用虚拟地址空间&#xff0c;虚拟地址空间每个进程的4g并不是真的有&a…

【ROS2】高级:安全-检查网络流量

目标&#xff1a;捕获和检查原始 ROS 2 网络流量。 教程级别&#xff1a;高级 时间&#xff1a;20 分钟 内容 概述 先决条件 运行演示 安装 tcpdump启动说话者和听者显示未加密的发现数据包显示未加密的数据包 启用加密显示加密的发现数据包显示加密数据包 概述 ROS 2 通信安全…

【Unity】Android Failed to transform Error while dexing.

文章目录 一、背景二、问题描述三、原因和解决方法 一、背景 1、Unity 2021.3.33f1 2、Firebase 11.7.0 3、升级至API-34 二、问题描述 错误信息 Failed to transform play-services-measurement-api-21.5.0.aar (com.google.android.gms:play-services-measurement-api:21.5.…

【yolov8】3、yolov8 环境安装 【GPU版】

pycharm下载安装 yolov8 环境安装 【GPU版】 1、要求1.1 什么是 CUDA 和 CUDNN1.2 查看cuda版本的3种方法&#xff08;版本在10.2以上的可以忽略本章节&#xff09;&#xff1a;1.3 没有找到NIVDIA图标&#xff0c;确认是否有英伟达显卡 2、pycharm下载安装进入官网 3、yolov8…