您的位置:首页 > 理论基础 > 计算机网络

同时处理TCP和UDP请求的回射服务器

2018-03-15 21:53 375 查看
server.cpp

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/epoll.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<fcntl.h>
#include<stdlib.h>
#include<sys/epoll.h>

#define MAX_EVENT_NUMBER 1024
#define TCP_BUFFER_SIZE 512
#define UDP_BUFFER_SIZE 1024

int setnonblocking(int fd)
{
int old_option = fcntl(fd, F_GETFL);
int new_option = old_option | O_NONBLOCK;
fcntl(fd, F_SETFL, new_option);
return old_option;
}

void addfd(int epollfd, int fd)
{
epoll_event event;
event.data.fd = fd;
event.events = EPOLLIN | EPOLLET;
epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
setnonblocking(fd);
}
int main(int argc, char* argv[])
{
if(argc != 2)
{
printf("usage: %s port\n", basename(argv[0]));
return 1;
}
int port = atoi(argv[1]);
int ret = 0;
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
assert
4000
(listenfd >= 0);

struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET; //ipv4
address.sin_addr.s_addr = htonl(INADDR_ANY);
address.sin_port = htons(port);

ret = bind(listenfd, (struct sockaddr*)&address, sizeof(address));
assert(ret != 1);

ret = listen(listenfd, 5);
assert(ret != -1);

/*创建UDP socket, 并将其捆绑到端口port上*/
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_ANY);
address.sin_port = htons(port);
int udpfd = socket(PF_INET, SOCK_DGRAM, 0);
assert(udpfd >= 0);

ret = bind(udpfd, (struct sockaddr*)&address, sizeof(address));
assert(ret != 1);

epoll_event events[MAX_EVENT_NUMBER];
int epollfd = epoll_create(5);
assert(epollfd != -1);
/*注册TCP socket 和 UDP socket 上的可读事件*/
addfd(epollfd, listenfd);
addfd(epollfd, udpfd);

while(1)
{
int number = epoll_wait(epollfd, events, MAX_EVENT_NUMBER, -1);
//printf("number = %d\n", number);
if(number < 0)
{
printf("epoll failure\n");
break;
}
for(int i = 0; i < number; i++)
{
int sockfd = events[i].data.fd;
if(sockfd == listenfd)
{
printf("connect arrived\n");
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof(client_address);
int connfd = accept(listenfd, (struct sockaddr*)&client_address, &client_addrlength);
if(connfd <= 0)
{
perror("accept ");
}
addfd(epollfd, connfd);
}
else if(sockfd == udpfd)
{
char buf[UDP_BUFFER_SIZE];
memset(buf, '\0', UDP_BUFFER_SIZE);
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof(client_address);
ret = recvfrom(udpfd, buf, UDP_BUFFER_SIZE - 1, 0,
(struct sockaddr*)&client_address, &client_addrlength);
if(ret > 0)
{
sendto(udpfd, buf, UDP_BUFFER_SIZE - 1, 0,
(struct sockaddr*)&client_address, client_addrlength);
}
}
else if(events[i].events & EPOLLIN)
{
char buf[TCP_BUFFER_SIZE];
while(1)
{
memset(buf, '\0', TCP_BUFFER_SIZE);
ret = recv(sockfd, buf, TCP_BUFFER_SIZE - 1, 0);
if(ret < 0)
{
if((errno == EAGAIN) || (errno == EWOULDBLOCK))
{
break;  //EAGAIN
//非阻塞模式下调用了阻塞操作,在该操作没有完成就返回这个错误
//这个错误不会破坏socket的同步,不用管它,下次循环接着recv就可以
}
close(sockfd);
break;
}
else if(ret == 0)
{
close(sockfd);
}
else
{
send(sockfd, buf, ret, 0);
}
}
}
else
{
printf("something else happend\n");
}
}
}
close(listenfd);
return 0;
}


tcp_client.cpp

/*************************************************************************
> File Name: client.c
> Author:Sanjingye
> Mail:
> Created Time: 2018年03月06日 星期二 16时28分05秒
************************************************************************/

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>

char* s_gets(char* st,int n)
{
char* ret_val;
int i=0;
ret_val=fgets(st,n,stdin);
if(ret_val)
{
while(st[i]!='\n'&&st[i]!='\0')
i++;
if(st[i]=='\n')
st[i]='\0';
else
while(getchar()!='\n')
continue;
}
return ret_val;
}

int main()
{
int serfd;
struct sockaddr_in server_address;
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8080);
if(inet_pton(AF_INET, "127.0.0.1",&server_address.sin_addr)==0)
{
printf("invalid server ip address\n");
return 1;
}
serfd = socket(AF_INET, SOCK_STREAM, 0);
if(serfd < 0)
{
perror("socket:");
return 1;
}
if((connect(serfd, (struct sockaddr*)&server_address, sizeof(server_address))) < 0)
{
perror("connect");
return 1;
}
char buff[1024];
while(1)
{
printf("client:> ");
s_gets(buff, 1024);
//puts(buff);
write(serfd, (void*)buff, strlen(buff));
if((read(serfd, (void*)buff, sizeof(buff))) <= 0)
{
break;
}
printf("server:> %s\n",buff);
}
close(serfd);
}


udp_client.cpp

/*************************************************************************
> File Name: udp_client.cpp
> Author:Sanjingye
> Mail:
> Created Time: 2018年03月14日 星期三 19时39分21秒
************************************************************************/

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>

char* s_gets(char* st,int n)
{
char* ret_val;
int i=0;
ret_val=fgets(st,n,stdin);
if(ret_val)
{
while(st[i]!='\n'&&st[i]!='\0')
i++;
if(st[i]=='\n')
st[i]='\0';
else
while(getchar()!='\n')
continue;
}
return ret_val;
}

int main()
{
int serfd;
struct sockaddr_in server_address;
socklen_t len = sizeof(server_address);
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8080);
if((inet_pton(AF_INET, "127.0.0.1", &server_address.sin_addr) == 0))
{
printf("invalid server ip address\n");
return 1;
}
serfd = socket(AF_INET, SOCK_DGRAM, 0);
if(serfd < 0)
{
perror("socket");
return 1;
}
char buff[1024];
while(1)
{
printf("udp_client:> ");
s_gets(buff, 1024);
sendto(serfd, buff, strlen(buff), 0,(struct sockaddr*)&server_address, len);
if((recvfrom(serfd, buff, 1024, 0, (struct sockaddr*)&server_address, &len)) < 0)
{
break;
}
printf("server:> %s\n", buff);
}
close(serfd);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐