使用 socket 接口需要在应用程序代码中包含两个头文件:
#include <sys/types.h>
#include <sys/socket.h>
socket()函数原型如下所示:
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
??socket()函数类似于 open()函数,用于创建一个网络通信端点,如果成功则返回一个网络文件描述符,通常把这个文件描述符称为 socket 描述符,这个 socket 描述符与文件描述符一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。
此函数执行成功时返回文件描述符,失败时返回-1。
示例:
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);//打开套接字
if (-1 == socket_fd)
{
printf("socket error!\n");
return -1;
}
......
......
close(socket_fd); //关闭套接字
函数原型如下所示:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
bind()函数用于将一个 IP 地址或端口号与一个套接字进行绑定。
sockaddr 的定义:
struct sockaddr{
unisgned short as_family;
char sa_data[14];
};
这个结构对用户并不友好,它把这些信息都封装在了 sa_data 数组中,不过由于系统的兼容性 , 我们一般使用另外一个结构 (struct sockaddr_in) 来代替。
sockaddr_in 的定义:
struct sockaddr_in{
unsigned short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
}
如果使用 Internet 所以 sin_family 一般为 AF_INET。
??调用 bind()函数将参数 sockfd 指定的套接字与一个地址 addr 进行绑定,成功返回 0,失败返回-1。
使用示例:
struct sockaddr_in socket_addr;
memset(&socket_addr, 0x0, sizeof(socket_addr)); //清零
//填充变量
socket_addr.sin_family = AF_INET;
socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
socket_addr.sin_port = htons(8888);
//将地址与套接字进行关联、绑定
bind(socket_fd, (struct sockaddr *)&socket_addr, sizeof(socket_addr));
??listen()函数只能在服务器进程中使用,让服务器进程进入监听状态,等待客户端的连接请求,listen()函数在一般在 bind()函数之后调用,在 accept()函数之前调用,它的函数原型是:
int listen(int sockfd,int backlog);
??服务器调用 listen()函数之后,就会进入到监听状态,等待客户端的连接请求,使用 accept()函数获取客户端的连接请求并建立连接。函数原型如下所示:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
为了能够正常让客户端能正常连接到服务器,服务器必须遵循以下处理流程:
??accept函数通常只用于服务器应用程序中,如果没有客户端请求连接,此时accept函数会进入阻塞状态,直到有客户端连接请求为止。
??当有客户端连接请求到达时,accept函数会与远程客户端建立连接,并且返回一个新的套接字,这个新的套接字与socket函数返回的套接字不同,我们后续与客户端进行数据交互是通过这个套接字。
??参数addr是一个传出参数,参数 addr 用来返回已连接的客户端的 IP 地址与端口号等这些信息。
??函数执行成功返回新的套接字,失败返回-1。
connect 函数的函数原型如下所示:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
??该函数用于客户端应用程序中,客户端调用 connect()函数将套接字 sockfd 与远程服务器进行连接,参数 addr 指定了待连接的服务器的 IP 地址以及端口号等信息,参数 addrlen 指定了 addr 指向的 struct sockaddr对象的字节大小。
??客户端通过 connect()函数请求与服务器建立连接,对于 TCP 连接来说,调用该函数将发生 TCP 连接的握手过程,并最终建立一个 TCP 连接,而对于 UDP 协议来说,调用这个函数只是在 sockfd 中记录服务器 IP 地址与端口号,而不发送任何数据。
??成功时返回 0,失败时返回-1。
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);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);