一、解释
socket地址其实就是一个结构体,封装端口号和IP等信息。后面的socket相关的api中需要用到这个socket地址。
客户端访问服务器,必须知道服务器的IP、 Port。
二、通用socket地址
(给IPv4用的)
#include <bits/socket.h>
struct sockaddr{
sa_family_t sa_family;
char sa_data[14];
};
typedef unsigned short int sa_family_t;
sa_family成员是地址族类型(sa_family_t)的变量。地址族类型通常与协议族类型对应。常见的协议族和对应的地址族如下所失。
协议族 | 地址族 | 描述 |
PF_UNIX | AF_UNIX | UNIX本地域协议族 |
PF_INET | AF_INET | TCP/IPv4协议族 |
PF_INET6 | AF_INET6 | TCP/IPv6协议族 |
sa_data成员用于存放socket地址值。但是,不同的协议族的地址值具有不同的含义和长度,如下图所示:
协议族 | 地址值含义和长度 |
PF_UNIX | 文件的路径名,长度可达108字节 |
PF_INET | 16bit端口号和32bit IPv4地址,共6字节 |
PF_INET6 | 16bit端口号,32bit流标识,128bit IPv6地址,32bit范围ID,共26字节 |
sa_data[14];我们只用6个字节来表示IPv4的地址数据,其中2个是端口号,4个是IP。剩下的8个都不写
因为14字节的sa_data根本无法容纳多数协议族的地址值。因此,Linux定义了下面新的通用的socket地址结构体,不仅提供了足够大的空间来存放地址值,而且是内存对齐的。
#include <bits/socket.h>
struct sockaddr_storage
{
sa_family_t sa_family;
unsigned long int _ss_align;
char _ss_padding[128-sizeof(_ss_align)];
};
typedef unsigned short int sa_family_t;
三、套接字函数
#include <sys/types.h>
#include <sys/socket.h>
#include <srpa/inet.h>
int socket(int domain,int type,int protocol);
-功能:创建一个套接字
-参数:
-domain:协议族
AF_INET:ipv4
AF_INET6:ipv6
AF_UNIX,AF_LOCAL:本地套接字通信(进程间通信)
-type:通信过程中使用的协议类型
SOCK_STREAM:流式协议
SOCK_DGRAM:报式协议
-protocol :具体的一个协议,一般写0;
-SOCK_STREAM :流式协议默认使用TCP
-SOCK_DGRAM:报式协议默认使用UDP
-返回值:成功:返回文件描述符,操作的就是内核缓冲区
失败:-1
int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen);
-功能:绑定,将fd和本地的IP+端口进行绑定
-参数:
-sockfd:通过socket函数得到的文件描述符
-addr:需要绑定的socket地址,这个地址封装了ip和端口号的信息
-addrlen:第二个参数结构体占的内存大小
int listen(int sockfd,int backlog);
-功能:监听这个socket上的连接
-参数:
-sockfd:通过socket()函数得到的文件描述符
-backlog:未连接的和已经连接的和的最大值 ,5
int accept(int sockfd,struct sockaddr *addr ,socklen_t *addrlen);
-功能:接受客户端连接,默认是一个阻塞的函数,阻塞等待客户端连接
-参数:
-sockfd:用于监听的文件描述符
-addr:传出参数,记录了连接成功后客户端的地址信息(ip,port)
-addrlen:指定第二个参数的对应内存大小
-返回值:
-成功:用于通信的文件描述符
-失败:-1
int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen);
-功能:客户端连接服务器
-参数:
-sockfd:用于通信的文件描述符
-addr:客户端要连接的服务器的地址信息
-addrlen:第二个参数的内存大小
-返回值:
-成功:0
-失败:-1