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;

}

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涂作权的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值