Socket详解

一.定义

Socket(套接字)是网络编程的核心,它允许不同主机或同一主机的不同进程之间进行通信,Socket API 提供了一套标准的接口,支持 TCP、UDP、IP 等协议

分为以下三个类型:

SOCK_STREAM:
用于tcp协议,可靠、面向连接、字节流,使用场景:HTTP、FTP、SSH


SOCK_DGRAM:
用于udp协议,不可靠、无连接、数据报,使用场景:DNS、视频流、游戏

SOCK_RAW:
用于IP/ICMP	原始套接字(直接访问网络层),使用场景:网络嗅探、自定义协议

地址结构:

IPV4:  struct sockaddr_in

struct sockaddr_in {
    sa_family_t sin_family; // 地址族(AF_INET)
    in_port_t sin_port;// 端口号(16位,需用 htons() 转换)
    struct in_addr sin_addr; // IP地址(32位,需用 inet_addr() 或 htonl())
    char sin_zero[8]; //填充(保持与 sockaddr 大小一致)
};

IPV6:struct sockaddr_in6

通用结构:struct sockaddr

struct sockaddr {
    sa_family_t sa_family; //地址族(AF_INET, AF_INET6, AF_UNIX)
    char sa_data[14]; //实际地址数据
};

二.API接口(核心)

socket():

作用:创建套接字

//头文件:
#include <sys/socket.h>

int socket(int domain,int type,int protocol);


domain --- 协议族(AF_INET、AF_INET6、AF_UNIX)
type --- 套接字类型(SOCK_STREAM、SOCK_DGRAM)
protocol --- 控制,通常填 0(自动选择,如 IPPROTO_TCP)

返回值:
-1 --- 创建失败
其他 --- 创建成功,并返回socketfd(套接字描述符)

举例:

#include <iostream>
#include <sys/socket.h>


int socketfd = socket(AF_INET,SOCK_STREAM,0);
//检查:
if(socketfd == -1){
    std::cerr<<"socket creation failed"<<std::endl;
    exit(EXIT_FAILURE);
}
//创建成功

bind():

绑定IP和端口

//头文件:
#include <sys/socket.h>

int bind(int socketfd,const struct sockaddr* addr,socklen_t addrlen);


//参数:
socketfd --- 套接字描述符
addr --- 指向 sockaddr_in 或 sockaddr_in6 的指针(需强制转换)
addrlen --- 地址结构的大小(sizeof(struct sockaddr_in))

//返回值:
-1 --- 绑定失败
其他(0)--- 绑定成功

举例:

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = INADDR_ANY;

if(bind(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr)
{ 
    perror("bind failed");
    exit(EXIT_FAILURE);
}

listen():

监听连接(TCP)

#include <sys/socket.h>

int listen(int sockfd,int backlog);


//参数:
sockfd --- 套接字描述符
backlog --- 等待连接队列的最大长度


//返回值:
-1 --- 失败
其他(0)--- 成功


举例:

if (listen(sockfd, 5) == -1) {
    perror("listen failed");
    exit(EXIT_FAILURE);
}

accept():

接收连接

#include <sys/socket.h>


int accept(int sockfd,struct socketaddr* addr,socklen_t* addrlen);


//参数:
sockfd --- 套接字描述符
addr --- 用于存储客户端地址
addrlen --- 地址结构大小(需先初始化)

//返回值:
-1 --- 连接失败
其他 --- 连接成功,返回的是新的套接字描述符

举例:

struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int connet_fd = accpet(sockfd,(struct socketaddr*)&client_addr,&client_len);
if(connet_fd == -1)
{
    perror("accept failed");
    exit(EXIT_FAILURE);
}
//连接成功

connect():

用户向服务器发起连接

#include <sys/socket.h>


int connect(int sockfd,const struct sockaddr *addr, socklen_t addrlen);


//参数:
sockfd --- 套接字描述符
addr --- 服务器地址
addrlen --- 地址结构大小

//返回值:
-1 --- 连接失败
其他(0)--- 连接成功

举例:

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htos(8080);
//解析IP:
inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr); 

//连接并判断:
if(connect(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr)) == -1)
{
    perror("connect failed");
    exit(EXIT_FAILURE);
}
//连接成功

send/recv:

TCP数据收发

#include <sys/socket.h>


//发送数据:
ssize_t send(int sockfd,const void *buf, size_t len, int flags);

//接收数据:
ssize_t recv(int sockfd,void *buf, size_t len, int flags);//buf内容要填充的,不能用const


//参数:
sockfd --- 已连接的套接字
buf --- 数据缓冲区
len --- 数据长度
flags --- 可选标志(如 MSG_WAITALL 阻塞直到收满)

//返回值:
-1 --- 失败
其他 --- 成功 并返回发送/接收的字节数

举例:

char buffer[1024];//缓冲区
ssize_t bytes_received = recv(connect_fd,buffer,sizeof(buffer),0);
if(bytes_received == -1)
{
    perror("recv failed");
}
else
{
    buffer[bytes_received] = '\0';  // 确保字符串终止
    printf("Received: %s\n", buffer);
}

sendto/recvfrom:

UDP数据收发

#include <sys/socket.h>

//发送数据:
ssize_t sendto(int sockfd,const void* buf,size_t len,int flags,const struct sockaddr* dest_addr,socklen_t addrlen);

//接收数据:
ssize_t recvfrom(int sockfd,void* buf,size_t len,int flags,struct sockaddr* src_addr,socklen_t* socklen);


//参数:
很多之前我们已经讲过了,讲下几个没讲的
dest_addr / src_addr --- 目标/源地址


//返回值:
-1 --- 发送、接收失败
其他 --- 返回发送/接收的字节数

举例:

struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
char buffer[1024];
ssize_t bytes_recvfrom = recvfrom(sockfd,buffer,sizeof(buffer),0,(struct sockaddr*)&client_addr,&client_len);
if(bytes_recvfrom == -1)
{
    perror("recvfrom failed");
}
//接收成功

close()

关闭套接字

#include <unistd.h>

//Linux系统下:
int close(int sockfd);



//补充:Windows系统下
#incluide <winsock2.h>
int closesocket(SOCKET sockfd);


//也是关闭连接,但是可以自己选择
int shutdown(int sockfd, int how);

//参数:
how --- 1.SHUT_RD:关闭读取    2.SHUT_WR:关闭写入    3.SHUT_RDWR:完全关闭

掌握这些 API 后,你可以实现基本的 TCP 服务器/客户端 和 UDP 通信了

最后,感谢你的支持!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jiaofi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值