Linux下的echo服务器
epoll模式下的echo服务器,忘记从哪个网页上粘贴过来的了,学习一下
/* * main.cc * * Created on: 2009-11-30 * Author: liheyuan * Describe: epoll实现阻塞模式服务器(Echo服务器) * * Last Date: 2009-11-30 * CopyRight: 2009 @ ICT LiHeyuan */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <arpa/inet.h> #include <netinet/in.h> #include <sys/epoll.h> #include <errno.h> #define EPOLL_SIZE 10 #define EVENT_ARR 20 #define BACK_QUEUE 10 #define PORT 18001 #define BUF_SIZE 16 void setnonblocking(int sockFd) { int opt; //获取sock原来的flag opt = fcntl(sockFd, F_GETFL); if (opt < 0) { printf("fcntl(F_GETFL) fail."); exit(-1); } //设置新的flag,非阻塞 opt |= O_NONBLOCK; if (fcntl(sockFd, F_SETFL, opt) < 0) { printf("fcntl(F_SETFL) fail."); exit(-1); } } int main() { int serverFd; //创建服务器fd serverFd = socket(AF_INET, SOCK_STREAM, 0); setnonblocking(serverFd); //创建epoll,并把serverFd放入监听队列 int epFd = epoll_create(EPOLL_SIZE); struct epoll_event ev, evs[EVENT_ARR]; ev.data.fd = serverFd; ev.events = EPOLLIN | EPOLLET; epoll_ctl(epFd, EPOLL_CTL_ADD, serverFd, &ev); //绑定服务器端口 struct sockaddr_in serverAddr; socklen_t serverLen = sizeof(struct sockaddr_in); serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); serverAddr.sin_port = htons(PORT); if (bind(serverFd, (struct sockaddr *) &serverAddr, serverLen)) { printf("bind() fail.\n"); exit(-1); } //打开监听 if (listen(serverFd, BACK_QUEUE)) { printf("Listen fail.\n"); exit(-1); } //死循环处理 int clientFd; sockaddr_in clientAddr; socklen_t clientLen; char buf[BUF_SIZE]; while (1) { //等待epoll事件的到来,最多取EVENT_ARR个事件 int nfds = epoll_wait(epFd, evs, EVENT_ARR, -1); //处理事件 for (int i = 0; i < nfds; i++) { if (evs[i].data.fd == serverFd && evs[i].data.fd & EPOLLIN) { //如果是serverFd,表明有新连接连入 if ((clientFd = accept(serverFd, (struct sockaddr *) &clientAddr, &clientLen)) < 0) { printf("accept fail.\n"); } printf("Connect from %s:%d\n", inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port)); setnonblocking(clientFd); //注册accept()到的连接 ev.data.fd = clientFd; ev.events = EPOLLIN | EPOLLET; epoll_ctl(epFd, EPOLL_CTL_ADD, clientFd, &ev); } else if (evs[i].events & EPOLLIN) { //如果不是serverFd,则是client的可读 if ((clientFd = evs[i].data.fd) > 0) { //先进行试探性读取 int len = read(clientFd, buf, BUF_SIZE); if (len > 0) { //有数据可以读,Echo写入 do { if (write(clientFd, buf, len) < 0) { printf("write() fail.\n"); } len = read(clientFd, buf, BUF_SIZE); } while (len > 0); } else if (len == 0) { //出发了EPOLLIN事件,却没有可以读取的,表示断线 printf("Client closed at %d\n", clientFd); epoll_ctl(epFd, EPOLL_CTL_DEL, clientFd, &ev); close(clientFd); evs[i].data.fd = -1; break; } else if (len == EAGAIN) { continue; } else { //client读取出错 printf("read() fail."); } } } else { printf("other event.\n"); } } } return 0; }
由于网页问题,粘贴过来的时候带着很多行号
写了个程序解决这个问题
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; /** * @author 作者 E-mail: * @version 创建时间:2015-10-30 下午02:38:17 类说明 处理从网页上粘贴过来的代码 */ public class Test { public static void main(String[] args) throws IOException { FileInputStream inputStream = new FileInputStream("source"); FileOutputStream outputStream = new FileOutputStream("res"); BufferedReader br = new BufferedReader(new InputStreamReader(inputStream)); int linenum = 0; final StringBuilder builder = new StringBuilder(); String tempstr = null; String subStr = null; while ((tempstr = br.readLine()) != null) { subStr = tempstr.substring(getSize(++linenum)); builder.append(subStr + '\n'); } outputStream.write(builder.toString().getBytes("gbk")); } public static int getSize(int lineNum) { int res = 1; while (lineNum / 10 > 0) { lineNum = lineNum / 10; res++; } return res; } }