一、网络四件套
#include <sys/types.h> //头文件;这四个文件一包,基本网络就无问题了;
#include <sys/socket.h>#include <netinet/in.h>
#include <arpa/inet.h>
二、socket创建套接字
socket是用来创建网络通信或本地通信的套接字,跟文件有关:告诉系统,PCB(进程控制块)控制的数据应该向哪个套接字写入、或读取;这个套接字是在TCP/IP协议下运行的
int socket(int domain, int type, int protocol);
三个参数:domain、type、protocol
1.domain:域名,领域,定义域(中文解释)
使用:表示程序员想要表示,通信在哪个域中进行?,是本地域通信?还是网络域通信?
本地域通信 [ AF_UNIX, AF_LOCAL (Local communication) ]
网络域通信 [ AF_INET (IPv4 Internet protocols)]
2.type:类型(中文解释)
使用:程序员想要表示:通信传输类型,是面向数据报还是面向字节流?
面向数据报:SOCK_DGRAM
面向字节流:SOCK_STREAM
3.protocol:协议(中文解释)
使用:前两个参数,一个在网络上通信(IPV4协议),一个规定了通信传输类型(TCP协议)两个组成了TCP/IP协议(传输层/网络层协议);一般来说,前两个订好了,第三个参数设置为0;
4.强行记下来
此函数写了不下5遍,一直忘了写:给自己做个笔记
int opt=1;
setsockopt(_listensock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); //如果程序挂了,则立刻可以按原来端口重新启动
三、bind绑定
IP地址:本地服务器接收数据的IP地址;细节:现实中,IP地址是配置在网卡上的;网络中的每一台服务器可以有多个网卡,也就意味着可以一个服务器可以有多个IP地址(无论是虚拟配置,还是现实配置);如果绑定单一的IP地址,意味着该进程只能从此进程只能接收该网卡的数据传送;其余的网卡对该进程无任何作用;所以使用参数INADDR_ANY;可以接受所有网卡的数据;只要端口号正确就行
port端口号:确定主机中的唯一程序;
bind:将用户设置的ip和port,在内核中和我们的进程强关联
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
参数:
1.sockfd:套接字
使用:socket的返回值->套接字
2.struct sockaddr结构体
这个结构体对象是要和网络进行绑定的;
2.1struct sockaddr结构体是一个通用型结构体
下图是他们在内存中的存储方式(具体的请看Linux头文件定义表)
struct sockaddr :通用结构体类型
struct sockaddr_in:网络通信使用此结构体:遵守IP协议
struct sockaddr_un:本地通信使用此结构体
sockaddr结构:
sockaddr_in结构:
in_addr结构:IP地址
绑定的套路:
struct sockaddr_in local;
memset(&local, 0, sizeof local);
local.sin_family = AF_INET;
local.sin_port = htons(port);
local.sin_addr.s_addr=ip.empty()?INADDR_ANY:inet_addr(ip.c_str());
int n = bind(listensock, (struct sockaddr *)&local, sizeof(local));
local.sin_family——16位地址类型:描述本地通信还是网络通信的结构体;这个结构体对象是用来网络通信还是本地通信;
local.sin_port——16位端口号:未来可能会把端口号发送给对方主机:所以要进行大端处理:函数htons();
local.sin_addr.s_addr——32位IP地址:将点分十进制换成4字节进制,并进行大端处理;函数inet_addr()
2.1大小端转化函数
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
2.2socklen_t addrlen: 结构体的长度;
3.总结
此函数的三个参数,sockfd套接字,告诉了系统向哪里写数据,并对此进行操作(并遵守TCP/IP协议);struct sockaddr定义了自己的IP地址和端口号;确定了网络上的唯一的锚点;完成了先描述的概念;两者绑定;
四、listen
监听:将套接字(文件描述符)变成监听状态;监视是否有链接进入;
// 开始监听socket (TCP, 服务器)
int listen(int socket, int backlog);
1.socket:套接字(文件描述符);将创建的套接字传入;
2.backlog:监听的队列;比如有大量的链接进入,只能连1个链接;剩余的没连上的‘就会等待被链接;
五、accept
// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address,
socklen_t* address_len);
描述:此函数为阻塞式函数;在未连接时,处于阻塞状态等待链接;链接完成后,则正常向下运行;而且,函数的返回值也是一个套接字;网络通信是通过返回的套接字与客服端通信;
六、connect
// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);