网络基础知识
1.网络主要是为了解决远距离、跨主机的数据通讯;
2.网络体系结构
为了保证数据在网络中完整性,安全性传输,网络将整个传输过程“分而治之”
1)OSI提供的七层网络的体系结构
2)TCP/IP四层网络体系结构
3.传输层协议:
1.TCP(传输控制协议)
TCP是传输层提供给应用层面向连接的数据传输服务;
面向连接:数据传输必须在建立连接的基础上
三次握手过程:
四次挥手过程:
2.UDP(用户数据报)
UDP是传输层提供给应用层面向无连接,不可靠的数据传输服务;
UDP特点:
1、资源消耗少,数据包头只有8BYTE字节,远比TCP协议包头要少;
2、不连接,所以也就不需要系统维护连接状态;
3、实时性是UDP的优势;
4.网络编程相关概念
1.IP:网络中主机的唯一标识,
本质:整形数
两种表示形式:1.点分十进制: 192.168.14.15
2.二进制数
IP的组成:
1.网络ID:主要是用于区分主机处于哪个网络
2.主机ID;主要是区分同一网络中不同的主机
分类:IPV4 / IPV6
2.端口:
主要是为了制定同一台主机上不同网络程序由谁来处理网络数据;
本质:16位整形数
3.网络字节序
由于网络数据是在不同的主机之间传送的,那么不同的主机字节序就可能会造成数据解析的错误,为了解决该问题,提出网络字节序这个规范标准;
,所有的主机按照大端字节序来存储数据;对于小端字节序的主机就需要转换数据后进行存储;
4.socket(套接字)
socket是网络编程的接口,简单理解就是应用层使用传输层提供服务的凭证。socket是一种特殊的I/O 接口,也是一种文件描述符;
网络编程
1.基于UDP协议的网络编程

套接字类型:
1、流式套接字 (SOCK_STREAM)
2、数据报套接字 (SOCK_DGRAM) 面向无连接
3、原始套接字 (SOCK_RAW)
服务器端:
1、(接口)创建套接字 socket
实现:int socket(int family,int type,int prot );
2、绑定自身地址信息(协议族,IP,端口)
实现:int bind(int sockfd,struct sockaddr addr,int addlen);
实际应用中 需要用 struct sockaddr_in 结构体替换;
3、从客户端接收数据
实现:int recvfrom(int sockfd,void buf,size_t size,int flag,struct sockaddr from,int len);
4、发送信息给客户端
实现int sendto(int sockfd,const void buf,size_t len,int flag,struct sockaddr to,int len);
5、关闭套接字
实现:int close(int sockfd);
客户端:
1、创建套接字 socket
实现:int socket(int family,int type,int prot );
2、指定对方(服务器端)地址信息(协议族,IP,端口)
实现:利用 struct sockaddr_in 结构体填充;
3、发送信息给服务器端
实现int sendto(int sockfd,const void buf,size_t len,int flag,
struct sockaddr to,int len);
4、从服务器端接收数据
实现:int recvfrom(int sockfd,void buf,size_t size,int flag,struct sockaddr from,int* len);
5、关闭套接字
实现:int close(int sockfd);
创建套接字 socket 
绑定套接字 bind
转换网络字节序 
h(host) to n (network)s (short)
n(network)to h (host) l (long)
接收数据的 recvfrom
发送数据的
sendto
2.基于UDP协议的网络编程2
2.1基于UDP的广播通讯
1、广播地址:
A:直接广播地址: 主机号 二进制位全为1;
B:受限广播地址:网络号和主机号二进制位都为1;255.255.255.255 INADDR_BROADCAST;
2、发送端流程:
1、创建数据报套接字 int sockfd = (AF_INET,SOCK_DGRAM,0);
2、设置套接字广播属性 setsockopt();
例;int enable = 1 ; setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&enable,4)
3、设置广播地址和广播端口
#define PORT 8888
struct sockaddr_in broadcast = {AF_INET};
broadcast.sin_port = PORT;
broadcast.sin_addr.s_addr =htonl(INADDR_BROADCAST);
4、向设置广播地址和广播端口发送数据:
int len = sizeof(struct sockaddr);
sendto(sockfd,str,strlen(str),0,(struct sockaddr*)&(brodcast),len);
3、接收端流程:
1、创建数据报类型套接字 :int sockfd = (AF_INET,SOCK_DGRAM,0);
2、绑定 INADDR_ANY ,广播端口到套接字
#define PORT 8888
struct sockaddr_in broadcast = {AF_INET};
broadcast.sin_port = htons(PORT);
broadcast.sin_addr.s_addr =htonl(INADDR_ANY);
bind(sockfd,(struct sockaddr)&broadcast,len);
3、接收广播
recvfrom();
4、发送响应数据
sendto(sockfd,str,strlen(str),0,(struct sockaddr)&(brodcast),len);
5、关闭套接字;
2.2基于UDP的组播通讯
1、组播地址:
永久组播地址:
临时组播地址:224.0.2.0~238.255.255.255
2、发送端流程:
1、创建数据报套接字 int sockfd = (AF_INET,SOCK_DGRAM,0);
2、设置组播地址和组播端口
#define PORT 8888
struct sockaddr_in multicast = {AF_INET};
multicast .sin_port = htons(PORT);
multicast .sin_addr.s_addr =inet_addr(“224.0.2.1”);
3、向设置组播地址和组播端口发送数据:
int len = sizeof(struct sockaddr_in);
sendto(sockfd,str,strlen(str),0,(struct sockaddr*)&(multicast),len);
4、接收数据
recvfrom()
5、关闭套接字
close(sockfd);
3、接收端流程:
1、创建数据报套接字 int sockfd = (AF_INET,SOCK_DGRAM,0);
2、绑定 INADDR_ANY ,组播端口到套接字
struct sockaddr_in multicast = {0};
multicast.sin_addr.s_addr = htonl(INADDR_ANY);
//inet_pton(AF_INET,”0.0.0.0”,multicast.sin_addr.s_addr);
multicast.sin_port =htons(MULTIPORT)
bind(sockfd,(struct sockaddr*)&multicast,len);
3、设置套接字IPPROTO_IP层的IP_ADD_MEMBERSHIP属性 setsockopt();
例子:
第一种:
struct in_addr multiaddr = {0};
multiaddr.s_addr = inet_addr(“224.0.2.1”);
struct in_addr localaddr = {0};
multiaddr.s_addr = inet_addr(“0.0.0.0”);
struct ip_mreqn mreq = {
.imr_multiaddr = multiaddr,
.imr_address = localaddr,
.imr_ifindex = if_nametoindex (“ens33”)
};
第二种:
struct ip_mreqn mreq = {.imr_ifindex = if_nametoindex(“ens33”)};
inet_pton(AF_INET, “224.0.2.1”, &mreq.imr_multiaddr);
inet_pton(AF_INET, “0.0.0.0”, &mreq.imr_address);
setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(struct ip_mreqn ));
4、接收组播信息
recvfrom();
5、发送响应数据
sendto(sockfd,str,strlen(str),0,(struct sockaddr*)&peer,len);
6、关闭套接字;
组播通讯相关结构体
struct ip_mreqn {struct in_addr imr_multiaddr; /* IP multicast groupaddress */struct in_addr imr_address; /* IP address of localinterface */int imr_ifindex; /* interface index */};struct ip_mreq {struct in_addr imr_multiaddr; /* IP multicast groupaddress */struct in_addr imr_interface; /* IP address of localinterface */};
3.基于TCP协议的网络编程


套接字类型:
1、流式套接字 (SOCK_STREAM)
2、数据报套接字 (SOCK_DGRAM) 面向无连接
3、原始套接字 (SOCK_RAW)
1、服务器端
需要两种功能的套接字:
1)主要用于监听客户端连接;
2)主要用于和客户端进行数据收发;
操作流程:
1、创建套接字(流式)int sockl = socket(AF_INET,SOCK_STREAM,0);//监听客户端连接
备注:创建出的该套接字用于监听客户端连接;
2、绑定自身地址信息
len = sizeof(struct sockaddr_in);
struct sockaddr_in server = {AF_INET};
server.sin_port = htons(PORT);
inet_pton(AF_INET,argv[1],&server.sin_addr);
bind(sockl,(struct sockaddr*)&server,len);
3、开始监听
listen(sockl,5);
4、接收客户端连接
accept();
5、发送数据给客户端
send()
6、从客户端接收数据
recv
7、关闭套接字
close(sockl);
2、客户端
1.创建套接字(流式)int sockfd = socket(AF_INET,SOCK_STREAM,0)
2.连接服务器
len = sizeof(struct sockaddr_in);
struct sockaddr_in server = {AF_INET};
server.sin_port = htons(PORT);
inet_pton(AF_INET,argv[1],&server.sin_addr);
connect(sockfd,(struct sockaddr)&server,len);
3.发送数据给服务器
send(int, const void buff, size_t len, int flags);
4.从服务器接收数据
recv(int, const void *buff, size_t len, int flags);
5.关闭套接字
close(sockfd);
4、基于TCP协议的并发服务器设计
1.socket + 多线程
设计思想:
1)让主线程用于接收客户端连接;
2)一旦接收某个客户端连接后,产生子线程,在子线程中和每个客户端进行数据的收发,
具体实现:
1.创建监听套接字;
2.绑定服务器端地址信息;
3.监听客户端连接;
4.实现一个while(1)循环;
5.在循环内,接收客户端连接;
6.一旦接收客户端连接,就创建一个子线程;
7.在线程函数中实现数据的收发,处理;
5、利用多路复用技术设计TCP并发服务器




多路复用技术核心:检测文件描述符状态,告知应用程序操作是否可以以非阻塞的方式进行;
多路复用技术应用于网络编程步骤:
服务器:
1、创建套接字
2、绑定服务器端地址信息
3、监听客户端连接
4、定义描述符集合并初始化
5、接收客户端连接
6、while(1)
7、添加0,通讯套接字 到描述符集合;
8、 调用select 函数,传递相应参数;
9、用 FD_ISSET 依次确定0,通讯套接字是否可读;
10、如果可读状态发生,则进行IO操作;如果获取的数据为quit 退出循环;
11、关闭套接字

