网络编程学习
文章来源:https://blog.csdn.net/weichanghu_/article/details/81711449
TCP通信的基本步骤如下:
服务端:socket---bind---listen---while(1){---accept---recv---send---close---}---close
客户端:socket----------------------------------connect---send---recv-----------------close
2. socket函数:生成一个套接口描述符
domain{ AF_INET:Ipv4网络协议 AF_INET6:IPv6网络协议}
type{tcp:SOCK_STREAM udp:SOCK_DGRAM}
protocol:指定socket所使用的传输协议编号。通常为0
int sfd = socket(AF_INET, SOCK_STREAM, 0);//
my_addr.sin_family = AF_INET; //表示采用Ipv4网络协议
my_addr.sin_port = htons(8888); //表示端口号为8888,通常是大于1024的一个值
my_addr.sin_addr.s_addr = inet_addr("192.168.0.101"); // inet_addr()用来将IP地址字符串转换成网络所使用的二进制数字;将my_addr.sin_port置为0,函数会自动为你选择一个未占用的端口来使用。同样,通过将my_addr.sin_addr.s_addr置为INADDR_ANY,系统会自动填入本机IP地址
3. bind函数:用来绑定一个端口号和IP地址,使套接口与指定的端口号和IP地址相关联
if(bind(sfd, (struct sockaddr*)&my_str, sizeof(struct socketaddr)) == -1)
4. listen函数:使服务器的这个端口和IP处于监听状态(阻塞?),等待网络中某一客户机的连接请求。如果客户端有连接请求,端口就会接受这个连接
int listen(int sockfd, int backlog);/ /backlog指定同时能处理的最大连接要求,通常为10或者5。 最大值可设至128
5. accept函数:接受远程计算机(远程客户端IP和端口等信息在第二个参数clientaddr中)的连接请求,建立起与客户机之间的通信连接。服务器处于监听状态时,如果某时刻获得客户机的连接请求,此时并不是立即处理这个请求,而是将这个请求放在等待队列中,当系统空闲时再处理客户机的连接请求。当accept函数接受一个连接时,会返回一个新的socket标识符,以后的数据传输和读取就要通过这个新的socket编号来处理,原来参数中的socket也可以继续使用,继续监听其它客户机的连接请求。(也就是说,类似于移动营业厅,如果有客户打电话给10086,此时服务器就会请求连接,处理一些事务之后,就通知一个话务员接听客户的电话,也就是说,后面的所有操作,此时已经于服务器没有关系,而是话务员跟客户的交流。对应过来,客户请求连接我们的服务器,我们服务器先做了一些绑定和监听等等操作之后,如果允许连接,则调用accept函数产生一个新的套接字,然后用这个新的套接字跟我们的客户进行收发数据。也就是说,服务器跟一个客户端连接成功,会有两个套接字。)
原型:int accept(int s,struct sockaddr * clientaddr,int * addrlen);
参数:s为前面socket的返回值.即sfd
clientaddr为结构体指针变量,和bind的结构体是同种类型的,系统会把远程主机的信息(远程主机的地址和端口号信息)保存到这个指针所指的结构体中。
addrlen表示结构体的长度,为整型指针
返回值:成功则返回新的socket处理代码new_fd,失败返回-1
6. recv函数:用新的套接字来接收远端主机传来的数据,并把数据存到由参数buf 指向的内存空间
7. send函数:用新的套接字发送数据给指定的远端主机 if(send(new_fd, "hello", 6, 0) == -1)
8. close函数:当使用完文件后若已不再需要则可使用close()关闭该文件,并且close()会让数据写回磁盘,并释放该文件(sfd,new_fd)所占用的资源
客户端:
1. connect函数:用来请求连接远程服务器,将参数sockfd 的socket 连至参数serv_addr 指定的服务器IP和端口号上去
int connect (int sockfd_c,struct sockaddr * serv_addr,int addrlen);//客户端sockfd_c ,服务器信息,长度
linux网络编程(完整版
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);//nfds:select函数的第一个参数,是所有加入集合的句柄值的最大那个值还要加1;timeout:<0出错;=0超时;>0在没有超时时检测到变化。
UDP通信流程图如下:
服务端:socket---bind---recvfrom---sendto---close
客户端:socket----------sendto---recvfrom---close
int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen);
该函数比send()函数多了两个参数,to表示目地机的IP地址和端口号信息,而tolen常常被赋值为sizeof (struct sockaddr)。sendto 函数也返回实际发送的数据字节长度或在出现发送错误时返回-1
int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen);
from是一个struct sockaddr类型的变量,该变量保存连接机的IP地址及端口号。
setsockopt
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
都必须要放在bind之前,另外通常是用于UDP的
单播、广播、组播(多播)
单播用于两个主机之间的端对端通信;
广播用于一个主机对整个局域网上所有主机上的数据通信, 广播的IP地址“192.168.0.255”和广播的端口号;
多播/“组播”,将网络中同一业务类型主机进行了逻辑上的分组,进行数据收发的时候其数据仅仅在同一分组中进行,其他的主机没有加入此分组不能收发对应的数据。IPv4多播地址采用D类IP地址确定多播的组。在Internet中,多播地址范围是从224.0.0.0到234.255.255.255。