admin 管理员组文章数量: 887021
Socket(套接字)是计算机网络中的一个抽象层,它允许应用程序通过网络进行通信。套接字用于跨网络的不同主机上的应用程序之间的数据交换。在互联网中,套接字通常基于 TCP(传输控制协议)或 UDP(用户数据报协议)来实现数据的可靠传输或快速传输。
Socket 的原意是“插座”,在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。Socket本质上是一个抽象层 它是一组用于网络通信的API,包括了一系列的函数和数据结构,它提供了一种标准的网络编程接口,使得应用程序可以在网络中进行数据传输。Socket本身并不是一个具体的实现,而是一个抽象的概念。不同的操作系统和编程语言可以通过不同的方式来实现Socket API。
程序也可以用IP+端口号进行唯一标识。那么这个程序的入口就被称作Socket
Socekt编程,我们将TCP协议简化一下,就只有三个核心功能:建立连接、发送数据以及接收数据
-
用 read() 读取从远程计算机传来的数据;
-
用 write() 向远程计算机写入数据。
只要用 socket() 创建了连接,剩下的就是文件操作了。
OSI七层协议
框架 | 内容 |
---|---|
应用层 | HTTP、FTP、Telnet 等等 |
表示层 | XDR、ASN.1、SMB、AFP、NCP、等等 |
会话层 | ASAP、SSH、RPC、NetBIOS、等等 |
传输层 | TCP、UDP、RTP、SCTP 等等 |
网络层 | IP、ICMP,IGMP等等 |
数据链路层 | 以太网,PPP, ATM等等 |
物理层 | 铜缆、网线、光缆、无线电等等 |
TCP/IP 协议族
TCP/IP协议中,OSI七层被简化为了四个层次。 TCP/IP模型中的各种协议,依其功能不同,被分别归属到这四层之中,常被视为是简化过后的七层OSI模型。
TCP/IP 中 应用层(应用) 传输层(连接服务) 网络层(网络) 数据链路层(路由器/转运中心) 物理层(网线)
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议
工作人员将手机打包好, 交给了物流(传输层)。接下来手机就到了转运中心(路由器),转运中心根据时间,成本等一系列因素决定下一步该发往哪一个转运中心(网络层)。决定好接下来发往哪一个转运中心后就开始用货车运输了,那么运输的过程就是数据链路层了,链路层负责将数据从一个端点送到另一个端点。那么货车行驶的道路就是物理层。几经周转,手机安全地送到了小明手上。 面向连接指的是先建立连接再发送数据,先去查看从发货地点到小明家中间可不可以进行运输,也就是先确认路可以走得通再发货。如果货物在运输过程中有损坏或者丢失就让京东重新发货,确保小明收到的手机是没有任何问题的。基于字节流的意思就是比如小明买了手机又买了手机配件,分开发货,几件物品不是在一个包裹里,一个一个发。
套接字的使用通常分为服务器端和客户端两部分:
服务器端套接字(Server Socket)
-
创建服务器套接字:服务器首先创建一个服务器套接字,指定一个端口号,并等待客户端的连接。
-
绑定端口:服务器套接字会绑定到一个特定的端口,以便客户端能够知道如何连接到服务器。
-
监听连接:服务器套接字进入监听状态,等待客户端的连接请求。
-
接受连接:当客户端尝试连接时,服务器套接字接受连接请求,并创建一个用于与该客户端通信的套接字。
-
数据交换:服务器和客户端通过这个新创建的套接字进行数据的读取和写入。
-
关闭连接:通信完成后,服务器关闭与客户端的连接,并可以继续监听新的连接请求。
用法
python
import socket
# 创建服务器套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定端口
server_socket.bind(('0.0.0.0', 8080))
# 监听连接
server_socket.listen(1)
print("服务器正在等待连接...")
# 接受连接
client_socket, client_address = server_socket.accept()
print(f"连接来自: {client_address}")
# 数据交换
data = client_socket.recv(1024)
print(f"收到数据: {data.decode()}")
# 发送数据
client_socket.send(b'Hello, Client!')
# 关闭连接
client_socket.close()
server_socket.close()
c语言实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[BUFFER_SIZE] = {0};
// 创建套接字文件描述符
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// 绑定套接字到端口
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// 监听是否有客户端连接
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
// 接受客户端连接
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
// 读取客户端数据
read(new_socket, buffer, BUFFER_SIZE);
printf("客户端消息: %s\n", buffer);
// 向客户端发送数据
const char *hello = "Hello from server";
send(new_socket, hello, strlen(hello), 0);
printf("Hello message sent\n");
// 关闭套接字
close(server_fd);
return 0;
}
客户端套接字(Client Socket)
-
创建客户端套接字:客户端创建一个套接字,用于与服务器通信。
-
指定服务器地址和端口:客户端指定服务器的IP地址和端口号,以便连接到正确的服务器。
-
发起连接:客户端尝试与服务器建立连接。
-
数据交换:一旦连接建立,客户端可以通过套接字发送请求和接收响应。
-
关闭连接:通信完成后,客户端关闭套接字,断开与服务器的连接。
用法
import socket
# 创建客户端套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接服务器
client_socket.connect(('localhost', 8080))
# 发送数据
client_socket.send(b'Hello, Server!')
# 接收数据
data = client_socket.recv(1024)
print(f"收到数据: {data.decode()}")
# 关闭连接
client_socket.close()
c语言实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[BUFFER_SIZE] = {0};
// 创建套接字文件描述符
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// 绑定套接字到端口
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// 监听是否有客户端连接
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
// 接受客户端连接
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
// 读取客户端数据
read(new_socket, buffer, BUFFER_SIZE);
printf("客户端消息: %s\n", buffer);
// 向客户端发送数据
const char *hello = "Hello from server";
send(new_socket, hello, strlen(hello), 0);
printf("Hello message sent\n");
// 关闭套接字
close(server_fd);
return 0;
}
Socket(套接字),用大白话来说,就像是你家里的门牌号码和信箱。在网络世界里,电脑或者设备要互相通信,它们也需要一个“门牌号码”来识别谁是谁,以及通过“信箱”来收发信息。
-
门牌号码:每个Socket都有一个独一无二的地址,包括IP地址(就像你家的小区、楼号、单元号)和端口号(就像你家的门牌号)。这样,网络数据包就能准确地找到对应的设备和应用程序。
-
信箱:Socket本身就像是个信箱,你可以把信息放进信箱里,等待邮递员(操作系统或者网络硬件)来取走并发送出去;同样,邮递员也可以把收到的信件放进信箱里,等待你去取。
-
敲门:当你想和另一台电脑的某个程序通信时,你的电脑会通过Socket去“敲门”,也就是发起连接请求。
-
聊天:一旦对方回应了你的连接请求,你们就可以开始“聊天”了。这个聊天可以是TCP这样的长对话,也可以是UDP这样的简短交流。
-
TCP套接字:如果你用TCP Socket,就像是打一个长时间的电话,你们会一直保持通话,直到通话结束。
-
UDP套接字:如果你用UDP Socket,就像是发邮件或者发短信,你发送信息过去,但对方不一定会立刻回复,甚至可能没有回复。
-
监听:服务器上的Socket常常处于“监听”状态,就像门卫一直在注意有没有人来敲门或者信箱里有没有信。
-
数据交换:无论是打电话还是发邮件,Socket都负责帮你打包信息,然后发送出去;同时,也帮你从信箱里取出收到的信息。
-
结束通信:当你和对方的“聊天”结束后,如果是TCP,你们会正式说“再见”,然后挂断电话;如果是UDP,你们可能就突然停止发送信息了。
-
多种用途:Socket可以用于各种网络通信,比如网页浏览、下载文件、视频聊天、在线游戏等等。
总之,Socket就是网络通信中的一个基础工具,它帮助不同的电脑和设备通过互联网找到对方,并且能够互相发送和接收信息。
本文标签: SOCKET
版权声明:本文标题:什么是Socket 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1729001053h1305383.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论