server端代码:
/*
UDP服务器
说明:用于在sigio信号处理程序中接收来自数据报客户端发来的数据报,接到的数据报存放
在一个队列中,随后程序主循环将从此队列中读取数据并进行处理。
用法:./server ip portnumber
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#define MAX_LENTH 1500
static int nqueue = 0 ;
void sigio_handler (int signum) //信号处理函数
{
if(signum == SIGIO){
nqueue++;
printf("signum=%d,nqueue=%d\n",signum, nqueue);
return;
}
}
static recv_buf[MAX_LENTH]; //接收数据的数组
int main (int argc, char* argv[])
{
int sockfd, on = 1;
struct sigaction action;
sigset_t newmask, oldmask;
struct sockaddr_in ser_addr;
if(argc != 3){ //执行程序时需要输入三个参数
printf("use: %s ip add port\n", argv[0]);
exit(EXIT_FAILURE);
}
memset(&ser_addr, 0, sizeof(ser_addr)); //将结构体置零
ser_addr.sin_family = AF_INET; //IPv4协议簇
ser_addr.sin_port = htons(atoi(argv[2])); //端口号
if(inet_aton(argv[1], (struct in_addr*) &ser_addr.sin_addr.s_addr) == 0){ //读取IP地址
perror("argv[1]");
exit(EXIT_FAILURE);
}
if(-1 == (sockfd = (socket(AF_INET, SOCK_DGRAM, 0)))){ //创建socket
perror("Create socket failed");
exit(EXIT_FAILURE);
}
if(-1 == (bind(sockfd, (struct sockaddr *) &ser_addr, sizeof(ser_addr)))){
perror("Bind socket failed");
exit(EXIT_FAILURE);
}
memset(&action, 0, sizeof(action));
action.sa_handler = sigio_handler;
action.sa_flags = 0;
sigaction(SIGIO, &action, NULL); //安装信号
if(-1 == fcntl(sockfd, F_SETOWN, getpid())){ //设置socket的拥有者
perror("Fcnt1 F_SETOWN");
exit(EXIT_FAILURE);
}
if(-1 == ioctl(sockfd, FIOASYNC, &on)){
perror("Ioctl FIOASYNC");
exit(EXIT_FAILURE);
}
sigemptyset(&oldmask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGIO);
printf("get ready\n");
while(1){
int len;
sigprocmask(SIG_BLOCK, &newmask, &oldmask);
while(nqueue == 0)
sigsuspend(&oldmask);
memset(&recv_buf, '\0', MAX_LENTH);
len = recv(sockfd, recv_buf, MAX_LENTH, MSG_DONTWAIT);
if(len == -1 && errno == EAGAIN){
nqueue = 0;
}
sigprocmask(SIG_SETMASK, &oldmask, NULL);
if(len > 0){
printf("recv %d byte(s), msg is %s\n",len, recv_buf);
}
}
}
client代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#define MAX_LENTH 1500
int main (int argc, char * argv[])
{
struct sockaddr_in addr;
int sock_fd, ret;
char snd_buf[MAX_LENTH];
if(argc != 3){
printf("use:%s ip_add port\n",argv[0]);
exit(EXIT_FAILURE);
}
memset(&addr, 0, sizeof(struct socketaddr_in*));
addr.sin_family = AF_INET;
if(0 == inet_aton(argv[1], (struct in_addr*) &addr.sin_addr.s_addr)){
perror("argv[1]");
exit(EXIT_FAILURE);
}
addr.sin_port = htons(atoi(argv[2]));
if(-1 == (sock_fd = socket(AF_INET, SOCK_DGRAM, 0))){
printf("Create socket failed\n");
exit(EXIT_FAILURE);
}
if(-1 == (ret = connect(sock_fd, (struct sockaddr*) &addr, sizeof(addr)))){
perror("Connect failed");
exit(EXIT_FAILURE);
}
while(1){
printf("input msg to send:");
memset(&snd_buf, '\0', MAX_LENTH);
int i =0;
fgets(snd_buf, MAX_LENTH - 1, stdin);
write(sock_fd, snd_buf, MAX_LENTH - 1);
//sendto(sock_fd,snd_buf, MAX_LENTH -1, 0 ,(struct sockaddr_in*)&addr, sizeof(struct sockaddr_in));
printf("send message %d:%s",i++,snd_buf);
}
}