首页 > 其他分享 >三次握手和四次挥手、UDP、TCP、粘包问题、模块回顾

三次握手和四次挥手、UDP、TCP、粘包问题、模块回顾

时间:2024-05-22 14:29:28浏览次数:21  
标签:UDP socket recv TCP server client send 粘包 data

【一】三次握手和四次挥手

【1】TCP协议的三次握手和四次挥手

  • TCP协议位于 osi 七层协议中的传输层

(1)使用三次握手来建立连接

  • 一次握手:
    • 客户端发送带有 SYN (SEQ=x)标志的数据包 ---》服务端,然后客户端进入 SYN_SEND 状态,等待服务器的确认。
  • 二次握手:
    • 服务端发送带有 SYN + ACK(SEQ=y,ACK=x+1)标志的数据包---》客户端,然后服务端进入 SYN_RECV 状态
  • 三次握手:
    • 客户端发送带有 ACK(ACK=y+1)标志的数据包---》服务端,然后客户端和服务端都进入 ESTABLISHED 状态,完成 TCP 三次握手。

(2)为什么要三次握手

  • 三次握手的目的是建立可靠的通信信道,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。
  • SYN:SYN=1 表示要建立连接
  • ACK:ACK=1 表示我收到了,允许
  • seq:随机数,建立连接无论客户端还是服务端要建立连接就要携带
  • ack:回应请求就要加1返回
  • FIN:表示断开连接
# 【1】第一次请求
# 由客户端发起请求 带SYN=1
# 表示我自己是客户端我要建立连接
# seq随机数带
# 发送给服务端
# 客户端 ---> 携带 SYN和SEQ ---> 发送给服务端
# 【2】第二次请求
# 服务端接收到客户端的请求
# ACK=1 表示收到了当前客户端发送给我的请求
# SYN=1 表示要建立连接
# seq:随机数
# 服务端 ---> 接收到客户端的请求,同意建立连接 ---> 发送给客户端
# 【3】第三次请求
# 客户端接收到了服务端的请求
# ACK=1 表示收到了当前服务端发送给我的请求
# SYN=1 表示要建立连接
# seq:随机数
# 和服务端建立连接成功

(3)使用四次挥手断开连接

  • 断开一个 TCP 连接则需要四次挥手,缺一不可:

  • 第一次挥手:

    • 客户端发送一个 FIN(SEQ=x)标志的数据包---》服务端,用来关闭客户端到服务器的数据传送。然后客户端进入 FIN-WAIT-1 状态。
  • 第二次挥手:

    • 服务器收到这个 FIN(SEQ=x)标志的数据包,它发送一个 ACK(ACK=x+1)标志的数据包---》客户端。然后服务端进入 CLOSE-WAIT 状态,客户端进入 FIN-WAIT-2 状态。
  • 第三次挥手:

    • 服务端发送一个 FIN(SEQ=y)标志的数据包---》客户端,请求关闭连接,然后服务端进入 LAST-ACK 状态。
  • 第四次挥手:

    • 客户端发送 ACK (ACK=y+1)标志的数据包->服务端,然后客户端进入TIME-WAIT 状态,服务端在收到 ACK (ACK=y+1)标志的数据包后进入 CLOSE 状态。此时如果客户端等待 2MSL 后依然没有收到回复,就证明服务端已正常关闭,随后客户端也可以关闭连接了。
# 【1】第一次
# 客户端向服务端发送请求,我想要断开连接
# 【2】第二次
# 服务端接收到客户端的请求
# 表示同意断开连接
# 【3】第三次
# 服务单向客户端发送请求,请求的原因是当前还有数据没有传输完成
# 请求等待,等待数据传输完成
# 发起请求,断开连接
# 服务端向客户端发送请求,请求断开连接
# 【4】第四次
# 客户端接收到服务端的请求
# 直接断开连接

【二】UDP协议模型

settings.py

# Author : chosen-yn
IP = '127.0.0.1'
# localhost 和 127.0.0.1区别
# DNS解析 --> 一串字符解析成IP
# localhost 就是一个域名 只能在本地使用
PORT = 8002
ADDR = (IP, PORT)

# 【一】解决办法一:通用 : 换 端口号
# 直接将启动的IP和端口号中的端口号更改
# 【二】解决办法二:加一个配置
# address already in use
# 【1】加配置
# SO_REUSEADDR : re 重新 use 使用 addr 地址
# server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定IP和PORT
# 【2】绑定端口
# server.bind(settings.ADDR)
# 【三】解决办法三:# OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。
# 【1】Windows
# 查看当前端口(cmd)对应的进程,杀死进程
# netstat -ano|findstr 8002
# 杀死当前进程PID对应的进程
# taskkill /pid PID号 /F

# 【2】MacOS/ linux
# ps aux|grep 端口号
# kill 进程号 -9
import hashlib


def encrypt_data(data, salt):
    data = str(data) + str(salt)
    data = data.encode()
    md5 = hashlib.md5()
    md5.update(data)
    return md5.hexdigest()


import struct

# 定义一个包含不同类型字段的格式字符串
format_string = 'i'


# 对数据进行打包
def pack_data(data_length: int):
    # 使用 struct.pack 将数据打包成二进制字节串
    packed_data = struct.pack(format_string, data_length)
    return packed_data


# 对数据解包
def unpack_data(data):
    data_length = struct.unpack(format_string, data)
    return data_length[0]
from conf import settings
# 【一】引入socket模块
import socket

# 【二】创建一个client对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_DGRAM:连接模式是UDP协议的报式模式
client = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
# 【三】直接发送数据
to_server_send_data = f'这是来自客户端的一条消息!'
to_server_send_data = to_server_send_data.encode()
client.sendto(to_server_send_data, settings.ADDR)
print(f'client :>>>> {client}')
# client :>>>> <socket.socket fd=428, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('0.0.0.0', 63316)>
# 【四】接收到服务端回的消息
from_server_recv_data,addr = client.recvfrom(1024)
from_server_recv_data = from_server_recv_data.decode()
print(f'from_server_recv_data :>>>> {from_server_recv_data}')
# from_server_recv_data :>>>> 这是来自服务端的一条消息!
# 【五】关闭连接对象
client.close()
from conf import settings
# 【一】引入socket模块
import socket

# 【二】创建一个server对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_DGRAM:连接模式是UDP协议的报式模式
# 只会发送一次数据
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
# 【三】绑定IP和PORT
server.bind(settings.ADDR)
print(f'server :>>>>{server}')
# server :>>>><socket.socket fd=332, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('127.0.0.1', 8002)>
# 【四】接收到客户端的数据
from_client_recv_data, addr = server.recvfrom(1024)
from_client_recv_data = from_client_recv_data.decode()
print(f'from_client_recv_data :>>>> {from_client_recv_data}')
# from_client_recv_data :>>>> 这是来自客户端的一条消息!
print(f'addr :>>>>{addr}')
# addr :>>>>('127.0.0.1', 58450)
# 【五】返回给客户端数据
to_client_send_data = '这是来自服务端的一条消息!'
to_client_send_data = to_client_send_data.encode()
server.sendto(to_client_send_data, addr)
# 【六】关闭连接和服务
server.close()

【三】TCP协议模型

from conf import settings
# 【一】引入socket模块
import socket

# 【二】创建一个client对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
client = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
# 【三】绑定IP和PORT
client.connect(settings.ADDR)
while True:
    # 【四】直接发送数据
    to_server_send_data = input("请输入发送给服务端的数据:>>>>>").strip()
    if not to_server_send_data:
        print(f'不允许发送空的数据')
        continue
    if to_server_send_data == 'q':
        print(f'当前连接退出!')
        break
    to_server_send_data = to_server_send_data.encode()
    client.send(to_server_send_data)
    # 【五】接收到服务端回的消息
    from_server_recv_data = client.recv(1024)
    from_server_recv_data = from_server_recv_data.decode()
    if from_server_recv_data == 'q':
        print(f'退出连接!')
        break
    print(f'这是来自服务端的数据:>>>>>{from_server_recv_data}')
# 【六】关闭连接对象
client.close()
from conf import settings
# 【一】引入socket模块
import socket

# 【二】创建一个server对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
# 【三】绑定IP和PORT
server.bind(settings.ADDR)
# 【四】监听连接对象
server.listen(5)
# 【五】建立连接对象
# 放在这里 进入的 while 循环中的哪个连接对象会一致不变
conn,addr = server.accept()
while True:
    try:
        # 这里面交流的对象永远是上面接收到的那一个
        # conn, addr = server.accept() : 接收到新的对象,忘记上一个连接过的对象
        # 【六】接收到客户端的数据
        from_client_recv_data = conn.recv(1024)
        from_client_recv_data = from_client_recv_data.decode()
        if not from_client_recv_data:
            break
        print(f'这是来自客户端的数据:>>>>{from_client_recv_data}')
        # 【七】返回给客户端数据
        while True:
            to_client_send_data = input("请输入发送给客户端的数据:>>>>>").strip()
            if not to_client_send_data:
                print(f'不允许发送空的数据')
            if to_client_send_data == 'q':
                print(f'退出系统')
            to_client_send_data = to_client_send_data.encode()
            conn.send(to_client_send_data)
            break
    except Exception as e:
        break
# 【八】关闭连接和服务
conn.close()
server.close()

【四】粘包问题

【1】粘包问题介绍

(1)粘包问题的背景

  • 只有 TCP 有粘包现象,UDP 永远不会粘包
  • TCP协议 ---》流式协议---》不断地传输数据
    • 例如有一盒颜料:先放红色的颜料,放了一盒,但是有一勺的量没有放进去
    • 没有放进去的红色颜料会和下一盒的绿色颜料混在一起
  • UDP协议---》报式协议---》一次性传输数据
    • 例如有一个大缸:先放红色的颜料放了一缸但是还有一勺没有放进去
    • 直接将这勺颜料扔了

(2)粘包问题

  • 客户端发送的数据远远超出服务端的接受范围,就导致了不同数据之间的数据混乱问题

(3)实例

  • 执行本地的 ipconfig 命令会获取到当前执行的结果
  • 将结果传递给服务端
  • 服务端接收到数据,只能接收一部分,另外一部分发现接收不到
  • 只能和第二次的数据合并到一起发送

(4)解决办法

  • 解决思路:
    • 问题产生在服务端
    • 原因是客户端向服务端发送数据,但是服务端不知道总的数据大小,只能按照默认的数据大小接收
  • 所以:
    • 客户端在发送数据的时候将数据的总大小一起发送给服务单
    • 服务单接收到总的大小的数据长度,根据自己的容量大小分批次接收

【2】问题演示

from conf import settings
# 【一】引入socket模块
import socket
import subprocess


def run_cmd(command):
    result = subprocess.run(
        command,  # 子进程要执行的命令
        shell=True,  # 执行的是shell的命令
        # 存放的是执行命令成功的结果
        stdout=subprocess.PIPE,
        # 存放的是执行命令失败的结果
        stderr=subprocess.PIPE,
        encoding="gbk",
        timeout=1)
    # returncode属性是run()函数返回结果的状态。
    if result.returncode == 0:
        return result.stdout
    else:
        return result.stderr


# 【二】创建一个client对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
client = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
# 【三】绑定IP和PORT
client.connect(settings.ADDR)
while True:
    # 【四】直接发送数据
    command = input("请输入需要执行的命令 :>>>> ").strip()
    if not command:
        print(f'不允许发送空的数据')
        continue
    if command == 'q':
        print(f'当前连接已退出!')
        break
    to_server_send_data = run_cmd(command=command)
    to_server_send_data = to_server_send_data.encode()
    client.send(to_server_send_data)
    # 【五】接收到服务端回的消息
    from_server_recv_data = client.recv(1024)
    from_server_recv_data = from_server_recv_data.decode()
    if from_server_recv_data == 'q':
        break
    print(f'这是来自服务端的数据 :>>>>  \n{from_server_recv_data}')
# 【六】关闭连接对象
client.close()
from conf import settings
# 【一】引入socket模块
import socket

# 【二】创建一个server对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 【三】绑定IP和PORT
server.bind(settings.ADDR)
# 【四】监听连接对象
server.listen(5)
# 【五】建立连接对象
# 放在这里 进入的 while 循环中的哪个连接对象会一致不变
conn, addr = server.accept()
while True:
    try:
        # 这里面交流的对象永远是上面接收到的那一个
        # conn, addr = server.accept() : 接收到新的对象,忘记上一个连接过的对象
        # 【六】接收到客户端的数据
        from_client_recv_data = conn.recv(1024)
        from_client_recv_data = from_client_recv_data.decode()
        if not from_client_recv_data:
            break
        print(f'这是来自客户端的数据 :>>>>  \n {from_client_recv_data}')
        # 【七】返回给客户端数据
        while True:
            to_client_send_data = input("请输入发送给客户端的数据 :>>>> ").strip()
            if not to_client_send_data:
                print(f'不允许发送空的数据')
                continue
            if to_client_send_data == 'q':
                print(f'当前连接已退出!')
            to_client_send_data = to_client_send_data.encode()
            conn.send(to_client_send_data)
            break
    except Exception as e:
        break
# 【八】关闭连接和服务
conn.close()
server.close()

【3】问题解决

from conf import settings
import socket
import subprocess
import json
import uuid


def run_cmd(command):
    result = subprocess.run(
        command,  # 子进程要执行的命令
        shell=True,  # 执行的是shell的命令
        # 存放的是执行命令成功的结果
        stdout=subprocess.PIPE,
        # 存放的是执行命令失败的结果
        stderr=subprocess.PIPE,
        encoding="gbk",
        timeout=1)
    # returncode属性是run()函数返回结果的状态。
    if result.returncode == 0:
        return result.stdout
    else:
        return result.stderr


# 【二】创建一个server对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
client = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
# 【三】绑定IP和PORT
client.connect(settings.ADDR)
while True:
    # 【四】直接发送数据
    command = input('请输入需要执行的命令:>>>>>').strip()
    if not command:
        print(f'不允许发送空的数据')
        continue
    if command == 'q':
        print('当前连接退出')
        break
    # 【1】执行本地的命令,获取到当前命令结果
    result = run_cmd(command=command)
    # 【2】对命令的结果进行编码---> 转成二进制数据
    result_bytes = result.encode()
    # 【3】计算长度
    data_length = len(result_bytes)
    # 【4】增加一个数据概览 --> 字典格式 做数据概览
    # 存储当前文件名 / 结果名 / md5加密盐(用来校验数据的完整性)
    salt = uuid.uuid4().hex
    encrypted = settings.encrypt_data(data=result_bytes, salt=salt)
    send_data_info = {
        'command': command,
        'data_length': data_length,
        'salt': salt,
        'encrypted': encrypted,
    }
    # 【5】将上面打包好的数据全部发送给服务端
    # (1)字典格式无法发送
    # 将字典转换为字符串数据 ----> json
    # dump : 处理文件数据
    # dumps : 做格式转换的
    json_str = json.dumps(send_data_info)
    # (2)将json字符串数据转换为二进制数据
    json_bytes = json_str.encode()
    # 【6】问题产生
    # JSON字符串转换为的二进制数据还是会很长
    # 让数据变短
    # struct 模块 ---> 将某几个数字转换为四个字节的二进制数据
    json_length_pack = settings.pack_data(data_length=len(json_bytes))
    # 【7】发送struct打包的数据(四个字节) + JSON数据 + 原始数据
    # JSON数据里面存的是所有数据信息而没有原始的二进制数据
    # 服务端接受的顺序取决于客户端发送的顺序
    # 先发送struct打包后的数据
    client.send(json_length_pack)  # 4 字节 --> 包含json二进制数据的长度
    # 发送 json_bytes 打包后的数据
    client.send(json_bytes)
    # 再发送 result_bytes 原始数据
    client.send(result_bytes)
    # 【五】接收到服务端回的消息
    from_server_recv_data = client.recv(1024)
    from_server_recv_data = from_server_recv_data.decode()
    if from_server_recv_data == 'q':
        break
    print(f"这是来自服务端的数据:>>>>>\n{from_server_recv_data}")
# 【六】关闭连接对象
client.close()
import json
from conf import settings
# 【一】引入socket模块
import socket

# 【二】创建一个server对象
# AF_INET:当前连接是基于网络的套接字
# SOCK_STREAM:连接模式是TCP协议的流式模式
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 【三】绑定IP和PORT
server.bind(settings.ADDR)
# 【四】监听连接对象
server.listen(5)
# 【五】建立连接对象
# 放在这里 进入的 while 循环中的哪个连接对象会一致不变
conn, addr = server.accept()
while True:
    #try:
        # 这里面交流的对象永远是上面接收到的那一个
        # conn, addr = server.accept() : 接收到新的对象,忘记上一个连接过的对象
        # 【六】接收到客户端的数据
        # 【1】先接接收四个字节的数据 ---> struct打包好的四个字节的数据
        json_pack_data = conn.recv(4)
        if not json_pack_data:
            break
        json_bytes_length = settings.unpack_data(data=json_pack_data)
        # 【2】根据json二进制数据长度解出JSON二进制数据
        json_data_bytes = conn.recv(json_bytes_length)
        # 【3】将json二进制数据转为json字符串数据
        json_str = json_data_bytes.decode()
        # 【4】将json字符串数据转换为python的字典
        data_info = json.loads(json_str)
        # 【5】从字典中获取自定的参数
        # 获取到总的数据长度
        # 10000
        data_length = data_info.get('data_length')
        # 【6】定义参数
        # (1)总数据
        # b'': 存在all_data 里的是二进制数据
        all_data = b''
        # (2)每次接收的数据大小
        size = 1024
        # data_length : 5
        # size : 2
        # count : 2 , last_size : 1
        # divmod:是以 data_length 去除以 size 取 count 为商,last_size为余数
        count, last_size = divmod(data_length, size)
        # (3)已经接受的数据大小
        all_size = 0
        while all_size < count + 1:
            all_size += 1
            # 接收到每一次的数据并和总数据拼接
            if all_size == count + 1:
                all_data += conn.recv(last_size)
            else:
                all_data += conn.recv(size)
        from_client_recv_data = all_data.decode()
        print(f'这是客户端的数据: \n{from_client_recv_data}')
        # 【七】返回给客户端数据
        while True:
            to_client_send_data = input("请输入发送给客户端的数据:>>>>>").strip()
            if not to_client_send_data:
                print(f'不允许发送空的数据')
                continue
            if to_client_send_data == 'q':
                print('退出连接')
            to_client_send_data = to_client_send_data.encode()
            conn.send(to_client_send_data)
            break
    # except Exception as e:
    #     break
# 【八】关闭连接和服务
conn.close()
server.close()

【4】subprocess模块回顾

import subprocess


def run_cmd(command):
    result = subprocess.run(
        command,  # 子进程要执行的命令
        shell=True,  # 执行的是shell的命令
        # 存放的是执行命令成功的结果
        stdout=subprocess.PIPE,
        # 存放的是执行命令失败的结果
        stderr=subprocess.PIPE,
        encoding="gbk",
        timeout=1)
    # returncode属性是run()函数返回结果的状态。
    if result.returncode == 0:
        return result.stdout
    else:
        return result.stderr


if __name__ == '__main__':
    print(run_cmd(['dir']))

【5】struct模块

# 【一】模块介绍
# ● struct.pack()是Python内置模块struct中的一个函数
# ● 它的作用是将指定的数据按照指定的格式进行打包
# 并将打包后的结果转换成一个字节序列(byte string),可以用于在网络上传输或者储存于文件中。
# 【二】参数简介
# struct.pack(fmt, v1, v2, ...)
# ● 其中,fmt为格式字符串,指定了需要打包的数据的格式,后面的v1,v2,...则是需要打包的数据。
# ● 这些数据会按照fmt的格式被编码成二进制的字节串,并返回这个字节串。

# 【三】示例
import struct

# 定义一个包含不同类型字段的格式字符串
format_string = 'i'

# 示例数据:整数、四个字节的原始数据、短整数
data_to_pack = '十七dasdadsad asd 撒大撒多所adsaddasdadsa da dsa asad撒大大带我去大青蛙大大大大大萨达去问问恰饭恰饭放散阀昂发昂发沙发阿发发发放上千万请发送方三房启发法阿发发发ad sada dsa dsa dsa sa dsa dsa as ad sad ad ada顿撒大大三大撒打我前端'
data_to_pack_bytes = data_to_pack.encode()

data_to_pack_len = len(data_to_pack_bytes)
print(data_to_pack_len)
# 使用 struct.pack 将数据打包成二进制字节串
packed_data = struct.pack(format_string, data_to_pack_len)

# 41000000
# 64000000
# 19010000
print("Packed data:", len(packed_data))  # 打印打包后的十六进制表示

# 解析二进制字节串,恢复原始数据
unpacked_data = struct.unpack(format_string, packed_data)
#
print("Unpacked data:", unpacked_data)  # 打印解析后的数据

标签:UDP,socket,recv,TCP,server,client,send,粘包,data
From: https://www.cnblogs.com/chosen-yn/p/18206173

相关文章

  • TCP图文详解到底什么是三次握手四次挥手
    为什么会有TCP/IP协议在世界上各地,各种各样的电脑运行着各自不同的操作系统为大家服务,这些电脑在表达同一种信息的时候所使用的方法是千差万别。就好像圣经中上帝打乱了各地人的口音,让他们无法合作一样。计算机使用者意识到,计算机只是单兵作战并不会发挥太大的作用。只有把......
  • 上海泗博HART转ModbusTCP网关HME-635应用案例之组态王和超声波液位计通信
    如今工业现场的应用也逐渐把现场的不同应用协议转换成以太网,以此来提升现场的通信速度和质量。ModbusTCP是工业以太网协议的一种,也是现场应用中最常使用的。本应用案例是基于ModbusTCP的组态王和基于HART的超声波液位计之间数据通讯的具体应用。应用图如下:  上海泗博HART......
  • 解锁服务器连接状态新姿势:tcping工具助你高效诊断网络连通性
    使用tcping工具检测服务器连接状态在IT运维环境中,由于安全考虑,很多服务器和交换机可能会禁用ICMP(InternetControlMessageProtocol)响应,即“ping”请求,以防止ICMPFLOOD攻击和不必要的资源消耗。然而,运维人员仍需要一种方法来验证与这些服务器的连接状态。在这种情况下,tcping......
  • ModbusTCP从站(服务端)扫描工具 python实现
    扫描指定IP网络下,有哪些modbusTCP服务端[1-247]frompymodbus.clientimportModbusTcpClientfrompymodbus.exceptionsimportModbusIOException,ConnectionException,NoSuchSlaveExceptionimporttimedefread_holding_registers(client,slave_address):""&quo......
  • 通信循环,粘包现象
    Ⅰ通信循环【一】UDP协议模型【1】UDP模板#服务端importsocketip_port=('127.0.0.1',9000)BUFSIZE=1024udp_server_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)udp_server_client.bind(ip_port)whileTrue:msg,addr=udp_server_clien......
  • Linux tcpdump 命令详解与示例
    命令概要Linux作为网络服务器,特别是作为路由器和网关时,数据的采集和分析是不可少的。tcpdump是Linux中强大的网络数据采集分析工具之一。用简单的话来定义tcpdump,就是:dumpthetrafficonanetwork,根据使用者的定义对网络上的数据包进行截获的包分析工具。作为互联网上经典的......
  • tcpdump使用
     1.服务器上执行tcpdump-iany-nnport6379|grephello 2.服务端执,特定主机和端口的链接(192.168.1.100为客户机器ip)tcpdump-iany-nnhost192.168.1.100andport6379|greohello 3.服务器上执行,保存到文件,文件可以使用Wireshark打开(可以字符串搜索内容)tcpd......
  • 粘包
    粘包问题【一】什么是粘包须知:只有TCP有粘包现象,UDP永远不会粘包【1】socket收发消息的原理首先需要掌握一个socket收发消息的原理发送端可以是一K一K地发送数据,而接收端的应用程序可以两K两K地提走数据,当然也有可能一次提走3K或6K数据,或者一次只提走几个字节的数据也就是说......
  • tcp协议
    TCP(TransmissionControlProtocol,传输控制协议)被描述为面向连接的和可靠的传输协议,这两个特性是其核心优势,下面分别解释这两个概念:###面向连接"面向连接"意味着在数据传输开始之前,通信双方必须先建立一个明确的连接。这个过程类似于打电话之前先拨号建立连接:1.**三次握手**:T......
  • 简述 TCP三次握手和四次挥手
    TCP首部的网络传输起到的作用:TCP的标志位每个TCP段都有一个目的,这是借助于TCP标志位选项来确定的,允许发送方或接收方指定哪些标志应该被使用,以便段被另一端正确处理。用的最广泛的标志是 SYN,ACK 和 FIN,用于建立连接,确认成功的段传输,最后终止连接。SYN:简写为S,同步标志位,......