用epoll实现简易的telnet

来源:互联网 发布:iscroll5.js 官网下载 编辑:程序博客网 时间:2024/06/09 20:33
我承认这篇文章有点标题党,呵呵。其实就是一个能和服务器建立全双工通信的客户端而已,用epoll机制实现。

上代码:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/epoll.h>#include <sys/socket.h>#include <arpa/inet.h>#include <unistd.h>#include <errno.h>//注意,不能一次性输入超过MAXLINE个的字符,否则程序会出错#define MAXLINE 1024//发生了致命错误,输出错误后立即退出  void error_quit(const char *str)      {      perror(str);  exit(1);      } //关闭连接,退出程序void close_connect(int sockfd){close(sockfd);printf("The connect have shutdown\n");exit(0);}int main(int argc, char **argv){int epfd, sockfd, nfs, tfd;   int readn, i, res;struct sockaddr_in servaddr;         struct epoll_event ev, events[256]; char buffer[MAXLINE];if( argc != 3 )    error_quit("usage: mytelnet <Address> <Port>");   //创建epoll事件处理机epfd = epoll_create(256);       if( -1 == epfd )  error_quit("epoll_create error");  //创建用于TCP协议的套接字     sockfd = socket(AF_INET, SOCK_STREAM, 0);    memset(&servaddr, 0, sizeof(servaddr));    servaddr.sin_family = AF_INET;    servaddr.sin_port = htons( atoi(argv[2]) );    res = inet_pton(AF_INET, argv[1], &servaddr.sin_addr);  //连接服务器if( res != 1 )error_quit("inet_pton error");   res = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));    if( res < 0 )error_quit("connect error");//注册socket事件ev.data.fd = sockfd;ev.events = EPOLLIN|EPOLLET; res = epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);        if( res < 0 )error_quit("epoll_ctl error");//注册标准输入事件ev.data.fd = STDIN_FILENO;ev.events = EPOLLIN|EPOLLET; res = epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev);     if( res < 0 )error_quit("epoll_ctl error");//开始事件循环while( 1 ){nfs = epoll_wait(epfd, events, 20, 500);for(i=0; i<nfs; i++){if(events[i].events & EPOLLIN)     {tfd = events[i].data.fd;memset(buffer, 0, MAXLINE);readn = read(tfd, buffer, MAXLINE);//有网络消息传来了if( sockfd == tfd ){if ( readn < 0)         {          // Connection Reset:你连接的那一端已经断开了,      //而你却还试着在对方已断开的socketfd上读写数据!        if (errno == ECONNRESET)        close_connect(sockfd);else error_quit("read error");}//连接正常关闭else if ( readn == 0 )       close_connect(sockfd);elseprintf("%s", buffer);}//标准输入if( STDIN_FILENO == tfd ){ev.data.fd = sockfd;      ev.events = EPOLLOUT|EPOLLET;       res = epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);      if( -1 == res )  error_quit("epoll_ctl error");  }}//如果有数据发送      else if(events[i].events & EPOLLOUT)       {      sockfd = events[i].data.fd;      write(sockfd, buffer, readn);   //注册用于读操作的文件描述符和事件      ev.data.fd = sockfd;      ev.events = EPOLLIN|EPOLLET;      res = epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);      if( -1 == res )  error_quit("epoll_ctl error");  }      }}return 0;}

编译与运行命令:gcc mytelnet.c -o mytelnet -levent./mytelnet 127.0.0.1 8877
用于测试的服务器:http://blog.csdn.net/aaa20090987/article/details/8769585
原创粉丝点击