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 地址和端口号唯一标识的通信端点

相关推荐
上海云盾安全满满6 小时前
为什么访问不一样的网站会有快有慢?
网络·安全
小熊officer6 小时前
网络渗透(Network Penetration)
网络·安全·web安全
长河6 小时前
APISIX
java·网络
FBI HackerHarry浩6 小时前
在Python中TCP网络程序开发的步骤流程
运维·服务器·开发语言·网络·python·pycharm
wanhengidc6 小时前
服务器 数据恢复
运维·服务器·网络·智能手机·云计算
熊出没6 小时前
我用 Netty TCP 搭建物联网云平台,并对接车辆电池信息解析
物联网·网络协议·tcp/ip
草莓熊Lotso7 小时前
【Linux网络】深入理解 HTTP 协议(一):从基础概念到 URL 编码解码
linux·网络·c++·网络协议·http·软件工程
aodunsoft8 小时前
安全月报 | 傲盾DDoS攻击防御2026年5月简报
网络·安全·ddos
jingling5558 小时前
Flutter | 从基本跳转到路由守卫
服务器·前端·网络·flutter·前端框架
SilentSamsara8 小时前
HTTP 客户端实战:httpx/重试/限速/连接池/中间件设计
开发语言·网络·python·http·青少年编程·中间件·httpx