を使用してソケットサーバーを実装しようとしていますepoll
。2つのタスクを実行する2つのスレッドがあります。
- 着信接続をリッスンする
- クライアントが送信しているデータを画面に書き込みます。
私のテストでは、クライアントとサーバーを同じマシン上に置き、3つまたは4つのクライアントを実行しています。サーバーは、:を発行してクライアントの1つを強制終了しなくなるまで正常に動作しCTRL-C
ます。強制終了すると、サーバーは他のクライアントからの非常に高速なデータのループと印刷を開始します。奇妙なことはそれです
- クライアントは2秒ごとにデータを送信しますが、サーバーのレートは高くなります
epoll_wait
また、EPOLLHUPまたはEPOLLERRもチェックしているため、クライアントの1つが切断されたときに何かを印刷することになっています。epoll_wait
私が彼に3000ミリ秒のタイムアウトを与えたので、印刷する前に少し待つ必要があります。
手伝ってくれますか?epoll記述子を他のスレッドに間違った方法で渡している可能性がありますか?コードが周りの多くの例に似ているので、私は理解できません。
どうもありがとう
Mn
// server.cpp
#include <iostream>
#include <cstdio>
#include <cstring>
extern "C" {
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <pthread.h>
}
#define MAX_BACKLOG 10
void* readerthread(void* args){
int epfd = *((int*)args);
epoll_event outwait[10];
while(true){
int retpw = epoll_wait( epfd, outwait,20, 3000 );
if( retpw == -1 ){
printf("epoll error %m\n");
}else if( retpw == 0 ){
printf("nothing is ready yet\n");
continue;
}else{
for( int i=0;i<retpw;i++){
if( outwait[i].events & EPOLLIN ){
int fd = outwait[i].data.fd;
char buf[64];
if( -1 == read(fd,buf,64) ){
printf("error reading %m\n");
}
printf("%s\n",buf);
}else{
std::cout << "other event" << std::endl;
}
}
}
}
}
int main(){
int epfd = epoll_create(10);
if( -1 == epfd ){
std::cerr << "error creating EPOLL server" << std::endl;
return -1;
}
pthread_t reader;
int rt = pthread_create( &reader, NULL, readerthread, (void*)&epfd );
if( -1 == rt ){
printf("thread creation %m\n");
return -1;
}
struct addrinfo addr;
memset(&addr,0,sizeof(addrinfo));
addr.ai_family = AF_INET;
addr.ai_socktype = SOCK_STREAM;
addr.ai_protocol = 0;
addr.ai_flags = AI_PASSIVE;
struct addrinfo * rp,* result;
getaddrinfo( "localhost","59000",&addr,&result );
for( rp = result; rp != NULL; rp = rp->ai_next ){
// we want to take the first ( it could be IP_V4
// or IP_V6 )
break;
}
int sd = socket( AF_INET, SOCK_STREAM, 0 );
if(-1==sd ){
std::cerr << "error creating the socket" << std::endl;
return -1;
}
// to avoid error 'Address already in Use'
int optval = 1;
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
if( -1==bind( sd, result->ai_addr, result->ai_addrlen ) ){
printf("%m\n");
std::cerr << "error binding" << std::endl;
return -1;
}
while(true){
std::cout << "listen" << std::endl;
if( -1== listen(sd, MAX_BACKLOG ) ){
std::cerr << "listen didn't work" << std::endl;
return -1;
}
std::cout << "accept" << std::endl;
sockaddr peer;
socklen_t addr_size;
int pfd = accept( sd, &peer ,&addr_size );
if( pfd == -1 ){
std::cerr << "error calling accept()" << std::endl;
return -1;
}
epoll_event ev;
ev.data.fd = pfd;
ev.events = EPOLLIN;
std::cout << "adding to epoll list" << std::endl;
if( -1 == epoll_ctl( epfd, EPOLL_CTL_ADD, pfd, &ev ) ){
printf("epoll_ctl error %m\n");
return -1;
}
}
}
// end of server.cpp
// client.cpp
#include <iostream>
#include <cstring>
#include <cstdio>
extern "C"{
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
}
int main(){
const char* servername = "localhost";
const char* serverport = "59000";
struct addrinfo server_address;
memset( &server_address, 0, sizeof(struct addrinfo) );
server_address.ai_family = AF_INET;
server_address.ai_socktype = SOCK_STREAM;
server_address.ai_protocol = 0; // any protocol
server_address.ai_flags = 0;
struct addrinfo * result, * rp;
int res = getaddrinfo( servername, serverport, &server_address, &result );
if( -1 == res ){
std::cout << "I cannot getaddress " << servername << std::endl;
return -1;
}
int fd = socket( server_address.ai_family
, server_address.ai_socktype
, server_address.ai_protocol );
if( -1 == fd ){
printf("I cannot open a socket %m\n");
return -1;
}
for( rp = result; rp != NULL; rp = rp->ai_next ){
std::cout << "************" << std::endl;
if( -1 == connect( fd, rp->ai_addr, rp->ai_addrlen ) ){
close(fd);
}else{
std::cout << "connected" << std::endl;
break;
}
}
if( rp == NULL ){
std::cerr << "I couldn't connect server " << servername << std::endl;
}
while(true){
sleep(2);
pid_t me = getpid();
char buf[64];
bzero( buf,sizeof(buf));
sprintf( buf,"%ld",me );
write(fd,buf,sizeof(buf));
printf("%s\n",buf);
}
}
// end of client.cpp