详细介绍: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

服务器端

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()

客户端

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

服务器端

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())

客户端

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

posted @ 2025-11-27 14:18  yangykaifa  阅读(20)  评论(0)    收藏  举报