简单的聊天室程序:客户端从标准输入输入数据后发送给服务端,服务端将用户发送来的数据转发给其它用户。这里采用IO复用poll技术。客户端采用了splice零拷贝。服务端采用了空间换时间(分配超大的用户数据数组,然后通过用户连接的文件描述符即可以索引到用户数据)
客户端程序:
#define _GNU_SOURCE 1//为了支持POLLRDHUP事件
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<poll.h>
#include<fcntl.h>
#include<iostream>
#define BUFFER_SIZE 64
using namespace std;
int main(int argc,char* argv[]){
if(argc<=2){
cout<<"argc<=2"<<endl;
return 1;
}
const char* ip=argv[1];//服务端地址
int port=atoi(argv[2]);
struct sockaddr_in address;
bzero(&address,sizeof(address));
address.sin_family=AF_INET;
inet_pton(AF_INET,ip,&address.sin_addr);
address.sin_port=htons(port);
int sockfd=socket(PF_INET,SOCK_STREAM,0);
assert(sockfd>=0);
if(connect(sockfd,(struct sockaddr*)&address,sizeof(address))<0){
cout<<"connect error"<<endl;
close(sockfd);
return 1;
}
pollfd fds[2];//pollfd结构体数组
fds[0].fd=0;//fds[0]是标准输入
fds[0].events=POLLIN;//注册可写事件
fds[0].revents=0;
fds[1].fd=sockfd;//fds[1]是socket描述符
fds[1].events=POLLIN|POLLRDHUP;//注册可写和挂起事件
fds[1].revents=0;
char read_buf[BUFFER_SIZE];
int pipefd[2];
int ret=pipe(pipefd);//创建一个管道,splice函数的参数必须有个是管道描述符(实现零拷贝)
assert(ret!=-1);
while(1){
ret=poll(fds,2,-1);//无限期等待注册事件发生
if(ret<0){
cout<<"poll error"<<endl;
break;