服务端
#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <netinet/in.h>
using namespace std;
#define PORT 8888
#define MAX_SIZE 1024
#define LISTENQ 1024
#define LINE_SIZE 1024
void epoll_add(int epollfd, int fd, int flag)
{
struct epoll_event event;
event.data.fd = fd;
event.events = EPOLLIN;
if (flag) {
event.events |= EPOLLET;
}
epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}
char buf[LINE_SIZE];
void process_event(struct epoll_event* event, int epollfd, int listenfd){
int ret, socketfd = event->data.fd;
if(socketfd == listenfd){
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
int connfd = accept(socketfd, (struct sockaddr*)&addr, &addrlen);
epoll_add(epollfd, connfd, true);
}
else if(event->events & EPOLLIN){
while(1){
memset(buf, 0, sizeof(buf));
ret = read(socketfd, buf, sizeof(buf)-1);
if(ret <= 0){
if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINTR)) {
epoll_ctl(epollfd, EPOLL_CTL_DEL, socketfd, NULL);
close(socketfd);
}
break;
}
else{
cout << "recv msg from: " << socketfd << " : " << buf << endl;
write(socketfd, buf, strlen(buf));
}
}
}
else {
cout << "unknown: " << event->data.fd << ", " << event->events << endl;
}
}
int main(int argc, char **argv)
{
int ret, listenfd;
struct sockaddr_in addr;
struct epoll_event events[MAX_SIZE];
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = INADDR_ANY;
listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
assert(listenfd >= 0);
ret = bind(listenfd, (struct sockaddr *)&addr, sizeof(addr));
assert(ret == 0);
ret = listen(listenfd, LISTENQ);
assert(ret == 0);
int epollfd = epoll_create(MAX_SIZE);
assert(epollfd >= 0);
epoll_add(epollfd, listenfd, true);
for (;;) {
ret = epoll_wait(epollfd, events, MAX_SIZE, -1);
assert(ret >= 0);
for(int i = 0; i< ret; i++){
process_event(&events[i], epollfd, listenfd);
}
}
close(listenfd);
return 0;
}
客户端
#include <iostream>
#include <string>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/epoll.h>
using namespace std;
#define PORT 8888
#define MAX_SIZE 1024
#define LISTENQ 1024
#define LINE_SIZE 1024
int client_init(string ip, string port){
int ret, socketfd;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(port.c_str()));
inet_pton(AF_INET, ip.c_str(), &addr.sin_addr);
socketfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
assert(socket > 0);
ret = connect(socketfd, (struct sockaddr *)&addr, sizeof(addr));
assert(ret == 0);
return socketfd;
}
bool epoll_add(int epollfd, int fd, int flags) {
struct epoll_event event;
event.events = EPOLLIN;
event.data.fd = fd;
if(flags)
event.events |= EPOLLET;
epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
}
void epoll_del(int epollfd, int fd){
epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL);
}
void process(int fd){
int ret, epollfd;
char sendbuf[LINE_SIZE], recvbuf[LINE_SIZE];
epollfd = epoll_create(5);
assert(epollfd > 0);
epoll_add(epollfd, fd, true);
epoll_add(epollfd, fileno(stdin), true);
struct epoll_event events[5];
for(;;){
ret = epoll_wait(epollfd, events, 5, -1);
for(int i = 0; i < ret; i++){
int socketfd = events[i].data.fd;
if(socketfd == fd && (events[i].events & EPOLLIN)){
read(fd, recvbuf, LINE_SIZE);
cout << string("recv from server: ") + recvbuf << endl;
}
else if(socketfd == fileno(stdin) && (events[i].events & EPOLLIN)){
memset(sendbuf, 0, sizeof(sendbuf));
if(fgets(sendbuf, LINE_SIZE, (stdin)) == NULL)
return;
write(fd, sendbuf, strlen(sendbuf)+1);
}
}
}
}
int main(int argc, char **argv){
if(argc != 3){
cout << "Usage: ./client $SERVER_IP $SERVER_PORT" << endl;
return 1;
}
int socketfd = client_init(argv[1], argv[2]);
assert(socketfd > 0);
process(socketfd);
return 0;
}
|