Socket和Websocket编程的区别

一、区别

WebSocket 和 Socket 之间的最大区别是它们是如何在应用程序和服务器之间传输数据的

(1)socket

Socket 是一个应用程序和底层操作系统之间的接口,它允许应用程序通过TCP 和 UDP 协议来发送和接收数据。Socket 主要用于客户端和服务器之间的数据传输。Socket 需要建立连接之后,才能进行数据传输。

通常情况下,应用程序通过使用套接字接口发送 TCP 协议的数据来实现 Socket。

(2)websocket

WebSocket 是一种网络协议,建立在 HTTP 协议之上,允许双向通信。WebSocket 协议允许服务器发送数据到客户端,同时也可以让客户端向服务器发送数据。WebSocket 使用 HTTP 协议的升级请求和响应来建立连接。WebSocket 的主要优点在于它可以通过单一的TCP连接来实现双向通信,从而减少了连接的开销并提高了数据传输的速度。

在总体上,WebSocket 相对于 Socket 来说,是一种更高级的技术。

Socket 处理低层次的网络传输,而 WebSocket 是在 HTTP 协议之上的二层协议,使用更容易,效率也更高,同时也支持双向实时通讯。

总体而言,socket和websocket的主要区别如下:

  1. 协议不同:Socket是基于传输层TCP协议实现的,而Websocket是基于HTTP协议的;Socket通信是通过Socket套接字来实现的,而Websocket通信是通过HTTP的握手过程实现的。
  2. 持久化连接:传统的socket通信是基于短连接的,通信完成后即断开连接;而websocket是基于长连接的,即建立连接后可以长久通信,避免了客户端和服务端频繁连接和断开的过程。
  3. 双向通信:传统的socket通信只支持单向通信,服务器只有接受到客户端的请求以后才能给予响应;websocket可以实现双向通信,即服务器和客户端之间可以相互请求和响应,实时通信效果更佳。
  4. 效率:socket通信具有高效性和实时性,因为传输数据的时候没有HTTP协议的请求头信息;websocket除了HTTP协议的请求头之外,还需要发送额外的数据,因此通信效率相对较低。

三、代码实现

(1)socket

服务器端

python 复制代码
import socket
import threading

# 服务器配置
HOST = '127.0.0.1'  # 本地主机
PORT = 65432        # 端口号

def handle_client(conn, addr):
    """处理客户端连接的线程函数"""
    print(f"新连接: {addr}")
    try:
        while True:
            # 接收数据,一次最多 1024 字节
            data = conn.recv(1024)
            if not data:
                break # 客户端关闭连接
            
            message = data.decode('utf-8')
            print(f"收到来自 {addr} 的消息: {message}")
            
            # 回复客户端,将消息转为大写
            response = f"Server received: {message.upper()}"
            conn.sendall(response.encode('utf-8'))
            
    except ConnectionResetError:
        print(f"客户端 {addr} 意外断开")
    finally:
        # 关闭连接
        print(f"连接关闭: {addr}")
        conn.close()

def start_socket_server():
    """启动 Socket 服务器"""
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        # 允许重用地址,避免"Address already in use"错误
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        
        s.bind((HOST, PORT))
        s.listen()
        
        print(f"Socket 服务器启动在 {HOST}:{PORT}, 等待连接...")
        
        while True:
            # 接受新连接
            conn, addr = s.accept()
            # 为每个新连接创建一个新线程处理
            thread = threading.Thread(target=handle_client, args=(conn, addr))
            thread.start()
            print(f"活动连接数: {threading.active_count() - 1}")

if __name__ == '__main__':
    start_socket_server()

客户端

python 复制代码
import socket

# 服务器配置
HOST = '127.0.0.1'
PORT = 65432

def start_socket_client():
    """启动 Socket 客户端"""
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        try:
            print(f"尝试连接到 {HOST}:{PORT}...")
            s.connect((HOST, PORT))
            print("连接成功!")

            messages = ["hello world", "python socket", "real-time data"]
            
            for msg in messages:
                print(f"\n发送: {msg}")
                s.sendall(msg.encode('utf-8'))
                
                # 接收服务器的响应
                data = s.recv(1024)
                print(f"收到响应: {data.decode('utf-8')}")
                
        except ConnectionRefusedError:
            print(f"连接失败: 无法连接到 {HOST}:{PORT}。请确保服务器已运行。")
        finally:
            print("客户端连接关闭。")

if __name__ == '__main__':
    start_socket_client()

(2)websocket

服务器端

python 复制代码
import asyncio
import websockets

# 服务器配置
HOST = '127.0.0.1'
PORT = 8765

async def echo(websocket):
    """处理 WebSocket 连接和消息"""
    print(f"新 WebSocket 连接: {websocket.remote_address}")
    try:
        async for message in websocket:
            print(f"收到消息: {message}")
            
            # 将收到的消息转为大写并发送回客户端
            response = f"Server echoed: {message.upper()}"
            await websocket.send(response)
            
    except websockets.exceptions.ConnectionClosedOK:
        print(f"WebSocket 连接正常关闭: {websocket.remote_address}")
    except websockets.exceptions.ConnectionClosedError as e:
         print(f"WebSocket 连接意外断开 ({e.code}): {websocket.remote_address}")
    finally:
        print(f"连接处理结束: {websocket.remote_address}")

async def start_websocket_server():
    """启动 WebSocket 服务器"""
    async with websockets.serve(echo, HOST, PORT):
        print(f"WebSocket 服务器启动在 ws://{HOST}:{PORT}, 等待连接...")
        await asyncio.Future()  # 永久运行

if __name__ == "__main__":
    asyncio.run(start_websocket_server())

客户端

python 复制代码
import asyncio
import websockets

# 服务器配置
URI = "ws://127.0.0.1:8765"

async def start_websocket_client():
    """启动 WebSocket 客户端"""
    try:
        async with websockets.connect(URI) as websocket:
            print(f"连接到 {URI} 成功!")
            
            messages = ["Async Python", "WebSocket Protocol", "Ping Pong Test"]
            
            for msg in messages:
                # 客户端发送消息
                await websocket.send(msg)
                print(f"\n发送: {msg}")

                # 客户端接收响应
                response = await websocket.recv()
                print(f"收到响应: {response}")

    except ConnectionRefusedError:
        print(f"连接失败: 无法连接到 {URI}。请确保 WebSocket 服务器已运行。")
    except websockets.exceptions.InvalidURI:
        print("错误: URI 格式不正确。")
    except Exception as e:
        print(f"发生其他错误: {e}")
    finally:
        print("\n客户端运行结束。")

if __name__ == "__main__":
    asyncio.run(start_websocket_client())

补充套接字的含义

"套接字"(Socket)在计算机网络编程中是一个非常核心的概念,尤其是在使用 socket 库进行网络通信时。

简单来说,套接字是应用程序与网络协议栈(TCP/IP 协议族)进行通信的接口或端点。 它是实现网络通信的一种抽象机制。

1. 编程接口 (API)

在编程层面,套接字是你调用网络功能的 API。

  • 当你用 Python 的 socket.socket() 创建一个对象时,你就创建了一个套接字。
  • 这个对象提供了一系列方法(如 bindlistenconnectsendrecv),允许你的应用程序执行网络操作。

打个比方: 套接字就像你家墙上的一个电话插孔

  • 你想打电话(发送/接收数据),你不需要知道电话线是怎么铺的,也不需要知道电信局的内部结构。
  • 你只需要把电话(你的应用程序)插到这个插孔(套接字)上,然后拨号(connect)或等待来电(listen)。
2. 通信端点(Endpoint)

在网络通信层面,一个套接字代表一个唯一的通信端点

对于互联网上的通信,一个完整的通信端点(即一个唯一的套接字标识)通常由以下 五元组 构成:
协议 + 源 IP 地址 + 源端口号 + 目标 IP 地址 + 目标端口号 \text{协议} + \text{源 IP 地址} + \text{源端口号} + \text{目标 IP 地址} + \text{目标端口号} 协议+源 IP 地址+源端口号+目标 IP 地址+目标端口号

  • IP 地址:标识了网络上的哪台主机。
  • 端口号:标识了主机上运行的哪个应用程序(进程)。

例如: 当你在浏览器中访问一个网页时:

  • 你的浏览器会创建一个套接字。
  • 这个套接字标识为:TCP + 你的电脑IP + 随机端口 + 服务器IP + 80/443端口
3. 系统资源(操作系统内核)

在操作系统内核层面,套接字是一个由操作系统维护的数据结构,用于记录和管理一次网络连接或通信的所有必要信息,包括:

  • 连接状态(例如:已连接、正在监听)。
  • 发送和接收数据的缓冲区。
  • 使用的协议(TCP、UDP 等)。
  • 本地和远程的地址/端口信息。
套接字总结
角色 套接字 (Socket) 的含义
对于程序员 调用网络功能的 API 对象。
对于网络通信 一次通信的唯一端点标识(IP + 端口)。
对于操作系统 维护网络连接状态和数据的内核资源

因此,当你说"socket 里面的套接字"时,通常指的就是那个用来进行网络数据交换、由 IP 地址和端口号唯一标识的通信端点

相关推荐
tuokuac4 小时前
如何判断“IP+端口“通不通
网络·网络协议·tcp/ip
AORO20255 小时前
防爆手机与普通的区别:应用场景、功能、未来发展
网络·5g·安全·智能手机·信息与通信
李白你好8 小时前
常见网络端口号及端口查看命令
网络
2301_8035545211 小时前
HTTP 常考问题简洁回答(速记版)
网络·网络协议·http
捷米研发三部12 小时前
Profinet 转 TCP/IP 协议转换网关:打破 PLC 与打标卡协议壁垒的工业通讯利器
网络·网络协议·tcp/ip
TeleostNaCl14 小时前
OpenWrt | 实现限制只有指定设备才能访问 luci 和 使用 SSH 等方式管理设备的方法
网络·经验分享·ssh·智能路由器
蒙娜丽宁15 小时前
Rust 并发编程进阶:线程模型、通道通信与异步任务对比分析
开发语言·网络·rust
Teable任意门互动16 小时前
主流多维表格产品深度解析:飞书、Teable、简道云、明道云、WPS
开发语言·网络·开源·钉钉·飞书·开源软件·wps
报错小能手16 小时前
计算机网络自顶向下方法2——网络、ISP连接结构介绍
网络·计算机网络