/*
udp服务器
说明:本程序为数据报服务器,用于在SIGIO信号处理程序中接受来自数据报客户端发来的数据报。收到的数据报存放在一个队列中,随后程序住循环将从队列中读取数据并进行处理
注意:本程序从命令行参数中获得服务器IP地址和端口,当命令行没有提供参数时,程序将使用默认值,即本机的任意IP
用法:./udpserver ip portnumber
*/
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
#include<errno.h>
#include<string.h>
#include<time.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netdb.h>
#include<arpa/inet.f>
#include<fcntl,h>
#define QUESIZE 16 //队列大小
#define BUFSIZE 512
struct request //客户端请求
{
<span style="white-space:pre"> </span>char *reqstr;
<span style="white-space:pre"> </span>size_t reqlen;
<span style="white-space:pre"> </span>struct sockaddr_in *peer;
<span style="white-space:pre"> </span>socklen_t sklen;
};
static struct request req_queue[QUESIZE];
static void bail(const char *on_what) //错误报告函数
{
<span style="white-space:pre"> </span>fputs(strerror(errno),stderr);
<span style="white-space:pre"> </span>fputs(": ",stderr);
<span style="white-space:pre"> </span>fputs(on_what,stderr);
<span style="white-space:pre"> </span>fputc(*\n*,stderr);
}
void do_sigio(int signum)
{
<span style="white-space:pre"> </span>int z;
<span style="white-space:pre"> </span>struct request *p_req;
<span style="white-space:pre"> </span>char buf[BUFSIZE];
for(;;)
{
<span style="white-space:pre"> </span>p_req=&req_queue[inx_in]; //保存下一个客户端请求数据包的位置索引
if(nqueue>=QUESIZE)
{
<span style="white-space:pre"> </span>write(stdout_FILENO,"request queue is full!\n",23);
<span style="white-space:pre"> </span>return;
}
z=recvfrom(s, //服务器套接字地址
q_req->reqstr, //接受缓存位置指针
BUFSIZE,
0,
(struct sockaddr*)p_req->peer, //客户端地址
&socklen);
if(z<0)
{
if((errno==EWOULDBLOCK)
break;
else
{
write(STDOUT_FILENO,"recvfrom error!\n",16);
exit(1);
}
}
q_req->reqstr[z]=0;
p_req->reqlen=z;
nqueue++;
if(++idx_in>=QUESIZE)
idx_in=0;
}
}
void init_queue()
{
for(int i=0;i<QUESIZE;i++)
{
if((req_queue[i].reqstr=malloc(BUFSIZE))==NULL||
(req_queue[i].peer=malloc(socklen))==NULL)
bail(init_queue");
req_queue[i].sklen=socklen;
}
idx_in=idx_out=nqueue=0;
}
static void install_sigio()
{
struct sigaction aigio_action;
memset(&sigio_action,0,sizeof(sigio_action));
sigio_action.sa_flags=0;
sigio_action.sa_handler=do_sigio;
if(sigaction(SIGIO,&sigio_action,NULL)==-1)
perror("Failed to set SIGIO");
}
void set_sockopt(int s,int flags)
{
fcntl(s,F_SETOWN,getpid());
if((flags=fcntl(s,F_GETFL,0))<0)
bail("F_GETFL error");
flags|=O_ASYNC|O_NONBLOCK;
if(fcntl(s,FSETFL,flags)<0)
bail("F_SETFL error");
}
linux信号驱动I/O模型服务器
最新推荐文章于 2024-08-21 02:48:12 发布