如何正确理解套接字
一、认识套接字
TCP用主机的IP地址加上主机上的端口号作为TCP连接的端点,这种端点就叫做套接字(socket)或插口。
套接字用(IP地址:端口号)表示。
它是网络通信过程中端点的抽象表示,包含进行网络通信必需的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
套接字(socket)是一种通信机制,凭借这种机制,客户/服务器系统的开发工作既可以在本地单机上进行,也可以跨网络进行,Linux所提供的功能(如打印服 务,ftp等)通常都是通过套接字来进行通信的,套接字的创建和使用与管道是有区别的,因为套接字明确地将客户和服务器区分出来,套接字可以实现将多个客 户连接到一个服务器。
但是说了半天,还是理解不了什么是套接字,其实这是一个狗屎一样的翻译问题:
谷歌翻译中socket直译为插座,字典中关于socket的解释为:an electrical device receiving a plug or light bulb to make a connection。译为:接收插头或灯泡以进行连接的电气设备。用c/s模型图来更好的理解插座的意义:
服务器就像一个大插排,包含很多插座,客户端就是像一个插头,每一个线程代表一条电线,客户端将电线的插头插到服务器插排上对应的插座上,就可以开始通信了。
数据传输需要通过协议,而套接字就是给数据传输添加协议的。
二、套接字特性
1、套接字属性
套接字的特性由3个属性确定,他们是,域,类型和协议
域指定套接字通信中使用的网络介质,最常见的套接字域是AF_INET,它指的是Internet网络
2、套接字类型
一个套接字可能有多种不同的通信方式
流套接字,流套接字提供一个有序,可靠,双向节流的链接,流套接字由类型SOCK_STREAM指定,它是在AF_INET域中通过TCP/IP链接实现的,这就是套接字类型(其实就是通信方式)
与流套接字相反,由类型SOCK_DGRAM指定的数据报套接字不建立和维持一个连接,它对可以发送的数据长度有限制,数据报作为一个单独的网络消息被传输,它可能会丢失,复制或乱序
3、套接字协议
套接字协议,通常使用默认就可以了(也就是最后一个参数填0)
三、基于套接字的TCP网络编程
1、创建流程概述
- socket创建一个套接字,SOCK_DGRAM是用在UDP上的,而SOCK_STREAM是用于TCP协议的。
- bind绑定IP和port
- listen使套接字变为可以被动链接
- accept等待客户端的链接
- close关闭资源
2、socket模块常用于TCP的方法
- connect(address):连接远程计算机
- send():发送数据
- recv():接收数据
- listen:开始监听,等待客户端连接
客户端实例:
-
from socket import *
-
#建立套接字,第二个参数是流式套接字 tcp专用
-
clientd_socket = socket(AF_INET,SOCK_STREAM)
-
#目标主机,也就是服务器的ip和端口
-
serverAddress = ('10.10.16.194',9999)
-
#主动和服务器发起链接
-
clientd_socket.connect(serverAddress)
-
-
data = input('请输入数据')
-
#发送数据
-
clientd_socket.send(data.encode('utf-8'))
-
#接受数据
-
re = clientd_socket.recv(128)
-
print(re.decode('utf-8'))
-
-
clientd_socket.close()
- accept():响应客户端的请求
阻塞当前线程
如果没有计算机连接,一直等待
如果有计算机连接,响应客户端
服务端实例:
-
from socket import *
-
server_socket = socket(AF_INET,SOCK_STREAM)
-
-
local_address = ('10.10.16.194',9999)
-
#绑定本机ip和端口,那么此程序就只接收此端口好的所有网络链接
-
server_socket.bind(local_address)
-
-
#限制接受5个客户端的数据
-
server_socket.listen(5)
-
#接受链接,如果没有链接那么处于阻塞状态。
-
#有链接的时候,accept会返回两个值,第一个是socket链接,第二个是远程地址
-
lianjie,remoteAddress = server_socket.accept()
-
re = lianjie.recv(128)
-
print(re.decode('utf-8'))
-
#发送数据
-
data = input('请输入发送内容')
-
lianjie.send(data.encode('utf-8'))
-
-
lianjie.close() #server_socket中的其中一个链接
-
server_socket.close() #server_socket相当于一个大的容器
先运行服务端,在运行客户端:结果
客户端:
服务端:
3、改进一下,让程序不会在一收一发后停止
客户端:
-
-
from socket import *
-
clientd_socket = socket(AF_INET,SOCK_STREAM)
-
serverAddress = ('10.10.16.194',9999)
-
clientd_socket.connect(serverAddress)
-
while True:
-
data = input('请输入数据')
-
clientd_socket.send(data.encode('utf-8'))
-
re = clientd_socket.recv(128)
-
print(re.decode('utf-8'))
服务端:
-
from socket import *
-
server_socket = socket(AF_INET,SOCK_STREAM)
-
local_address = ('10.10.16.194',9999)
-
server_socket.bind(local_address)
-
server_socket.listen(5)
-
lianjie,remoteAddress = server_socket.accept()
-
while True:
-
re = lianjie.recv(128)
-
print(re.decode('utf-8'))
-
data = input('请输入发送内容')
-
lianjie.send(data.encode('utf-8'))
-
lianjie.close()
-
server_socket.close()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗