首页 > 代码库 > 4高并发服务器:UDP局域网服务器(组播)
4高并发服务器:UDP局域网服务器(组播)
1 UDP局域网服务器
A读出每一个客户端发送过来的数据包,然后fork出子进程,由子进程去处理客户端请求。
B客户端与服务器段交换多个数据报,服务器为每一个客户端连接创建新的socket,在其上bind一个临时端口,然后用该socket处理对应客户端上的所有应答,这个办法要求在客户查看服务器第一个应答中的源端口号。然后后面利用此端口号和服务器进行交互。
2函数声明
int bind(int sockfd, const struct sockaddr*addr,socklen_t addrlen);
3依赖的头文件
#include<sys/types.h>
#include<sys/socket.h>
4函数说明:
addr中端口号为0,则使用临时端口号
注意:UDP是有可能出现接收缓冲区满,再接收数据时丢包。
A改变接收缓冲区大小
int n = 220 * 1024
setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,&n, sizeof(n));
B服务器应用层设计流量控制,控制发送数据速度。
5组播
组播组可以是永久的也可以是临时的,组播地址中,有一部分由官方分配的,称为永久组播组。永久组播组保持不变的是它的ip地址,组中的成员构成可以发生变化。永久组播组中的成员的数量都可以是任意的,甚至可以为零。那些没有保留下来的永久组播使用的ip组播地址,可以被临时组播组利用。
224.0.0.0~224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;
224.0.1.0~224.0.1.255是公用组播地址,可以用于Internet;
224.0.2.0~238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效;
239.0.0.0~239.255.255.255为本地管理组播地址,仅在特定的本地范围内有效。
ip ad查看网卡编号
man if_nametoindex,可以查看if_nametoindex的信息。
案例说明:
server.c
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <net/if.h> #define SERVER_PORT 8000 #define CLIENT_PORT 9000 #define MAXLINE 1500
#define GROUP "239.0.0.2"
int main(void) { int sockfd, i ; struct sockaddr_in serveraddr, clientaddr; char buf[MAXLINE]; char ipstr[INET_ADDRSTRLEN]; /* 16 Bytes */ socklen_t clientlen; ssize_t len; struct ip_mreqn group; /*构造用于UDP通信的套接字 */ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; /* IPv4 */ serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); /* 本地任意IP INADDR_ANY = 0 */ serveraddr.sin_port = htons(SERVER_PORT);
bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
/*设置组地址*/ inet_pton(AF_INET, GROUP, &group.imr_multiaddr); /*本地任意IP*/ inet_pton(AF_INET, "0.0.0.0", &group.imr_address); /* eth0 -->编号 命令:ip ad */ group.imr_ifindex = if_nametoindex("eth0");
setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, &group, sizeof(group));
/*构造 client地址 IP+端口 */ bzero(&clientaddr, sizeof(clientaddr)); clientaddr.sin_family = AF_INET; /* IPv4 */ inet_pton(AF_INET, GROUP, &clientaddr.sin——ANY_addr.s_addr); clientaddr.sin_port = htons(CLIENT_PORT);
while (1) { fgets(buf, sizeof(buf), stdin); sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&clientaddr, sizeof(clientaddr)); }
close(sockfd); return 0; } |
client.c
#include <netinet/in.h> #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <string.h> #include <stdlib.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <net/if.h>
#define SERVER_PORT 8000 #define MAXLINE 4096
#define CLIENT_PORT 9000 #define GROUP "239.0.0.2"
int main(int argc, char *argv[]) { struct sockaddr_in serveraddr, localaddr; int confd; ssize_t len; char buf[MAXLINE]; /*组播结构体 */ struct ip_mreqn group;
//1.创建一个socket confd = socket(AF_INET, SOCK_DGRAM, 0);
//2.初始化本地端地址 bzero(&localaddr, sizeof(localaddr)); localaddr.sin_family = AF_INET; inet_pton(AF_INET, "0.0.0.0" , &localaddr.sin_addr.s_addr); localaddr.sin_port = htons(CLIENT_PORT); bind(confd, (struct sockaddr *)&localaddr, sizeof(localaddr));
/*设置组地址*/ inet_pton(AF_INET, GROUP, &group.imr_multiaddr); /*本地任意IP*/ inet_pton(AF_INET, "0.0.0.0", &group.imr_address); /* eth0 -->编号 命令:ip ad */ group.imr_ifindex = if_nametoindex("eth0");
/*设置client加入多播组 */ setsockopt(confd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &group, sizeof(group));
while (1) { len = recvfrom(confd, buf, sizeof(buf), 0, NULL, 0); write(STDOUT_FILENO, buf, len); }
close(confd); return 0; } |
4高并发服务器:UDP局域网服务器(组播)