socket 分为服务器端和客户端
TCP socket的流程图
sever端:
1.socket函数
socket() 函数用来创建套接字,确定套接字的各种属性
NAME
socket - create an endpoint for communication
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
//int domain ip地址的类型 AF_INET 或者 AF_INET6
//int type 套接字类型 SOCK_STREAM(流格式套接字/面向连接的套接字) 和 SOCK_DGRAM(数据报套接字/无连接的套接字)
//int protocol 传输协议类型 IPPROTO_TCP或者 IPPTOTO_UDP 一般写0,系统会根据第二个参数自己选择。
RETURN VALUE
On success, a file descriptor for the new socket is returned. On error, -1 is returned, and
errno is set appropriately.//成功返回一个代表套接字的文件描述符,失败返回-1并设置errno
2.bind函数
在服务器端,bind() 函数将套接字与特定的 IP 地址和端口绑定起来,只有这样,流经该 IP 地址和端口的数据才能交给套接字处理。
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
//int sockfd 从socket函数接收到的文件描述符
//struct sockaddr *addr addr为sockaddr结构体的指针
//socklen_t addrlen addr的大小用sizeof(addr)来计算
RETURN VALUE
On success, zero is returned.
On error, -1 is returned, and errno is set appropriately.//成功返回0,失败返回-1并设置errno
sockaddr 结构体
struct sockaddr {
sa_family_t sa_family;//IP地址类型 2个字节
char sa_data[14];//属性数据 14个字节
}
sockaddr_in结构体(man 7 ip )
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET 2个字节*/
in_port_t sin_port; /* port in network byte order 2 个字节 */
struct in_addr sin_addr; /* internet address 4个字节*/
char sin_zero[8]; //不使用,一般用0填充 8个字节
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order 32位地址 */
};
uint32_t等价于unsigned int 所以s_addr是个整型数,而ip地址(192.168.1.1)是个字符串必须进行转换。
两个函数转换网络字节序
in_addr_t inet_addr(const char *cp);//只支持IPV4
int inet_pton(int af, const char *src, void *dst);
可以看成sockaddr是对sockaddr_in进行了二次“封装”
sockaddr 和 sockaddr_in 的长度相同,都是16字节,只是将IP地址和端口号合并到一起,用一个成员 sa_data 表示。要想给 sa_data 赋值,必须同时指明IP地址和端口号,例如”127.0.0.1:80“,遗憾的是,没有相关函数将这个字符串转换成需要的形式,也就很难给 sockaddr 类型的变量赋值,所以使用 sockaddr_in 来代替。这两个结构体的长度相同,强制转换类型时不会丢失字节,也没有多余的字节。
3.listen函数 侦听 将主动套接字变成被动套接字
当客户端没有发送请求时,套接字处于睡眠状态,当收到客户端的请**
求时,将套接字唤醒。
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);**
//int sockfd 直接创建的套接字文件描述符
//int backlog 客户端请求队列的最大值
RETURN VALUE
On success, zero is returned. On error, -1 is
returned, and errno is set appropriately.
4.accept函数 阻塞 等待客户端的请求
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
// accept() 返回一个新的套接字来和客户端通信,addr 保存了客户端的IP地址和端口号,最后一个参数是&addlen。
//socklen_t addrlen = sizeof(clientaddr);
RETURN VALUE
On success, these system calls return a nonnegative integer that is a descriptor for the accepted socket.
On error, -1 is returned, and errno is set appropriately.
//成功返回一个表示客户端套接字的文件描述符
5.读写数据
接收: read()或者recv()函数
发送: write()或者send()函数
6.关闭文件
client端
1.socket创建套接字
2.填充 sockaddr_in 结构体
3.连接到服务端
4.收发数据
5.关闭文件
connect函数连接到服务端
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
RETURN VALUE
If the connection or binding succeeds, zero is returned.
On error, -1 is returned, and errno is set appropriately.
实例链接:https://blog.csdn.net/qq_43921241/article/details/99115361