首页 > 代码库 > 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.0224.0.0.255为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;

224.0.1.0224.0.1.255是公用组播地址,可以用于Internet

224.0.2.0238.255.255.255为用户可用的组播地址(临时组地址),全网范围内有效;

239.0.0.0239.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局域网服务器(组播)