ネットワークプログラミング:マルチスレッド同時サーバー
考え方:ループ待機接続、接続に成功した後、サブスレッドを作成して接続のデータ通信を処理し、メインスレッドは接続を待機し続けます.ソケットインタフェースパッケージ:
サーバ側コード:
テスト:
#include "wrap.h"
#include
#include
#include
void sys_err(const char *ch)
{
perror(ch);
exit(1);
}
int Socket(int domain, int type, int protocol)
{
// socket
int ret = socket(domain,type,protocol);
if(ret == -1)
{
sys_err("socket error");
}
return ret;
}
int Setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen)
{
int ret = setsockopt(sockfd,level,optname,optval,optlen);
if(ret == -1)
{
sys_err("setsockopt error");
}
return ret;
}
int Bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen)
{
// ip
int ret = bind(sockfd,addr,addrlen);
if(ret == -1)
{
sys_err("socket bind error");
}
return ret;
}
int Listen(int sockfd, int backlog)
{
//
int ret = listen(sockfd,backlog);
if(ret == -1)
{
sys_err("socket listen error");
}
return ret;
}
int Accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
int fdc = 0;
again:
//
fdc = accept(sockfd,addr,addrlen);
if (fdc == -1)
{
if (errno == ECONNABORTED || errno == EINTR)
{
goto again;
}else
{
sys_err("socket accept error");
}
}
return fdc;
}
int Connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen)
{
int ret = 0;
ret = connect(sockfd,addr,addrlen);
if(ret == -1)
{
sys_err("connect error");
}
return ret;
}
int Close(int fd)
{
int ret = close(fd);
if(ret == -1)
{
sys_err("close error");
}
return ret;
}
サーバ側コード:
#include "wrap.h"
#include
#include
#include
#include //toupper
#include
#include //inet_ntop
#include //bzero
#define PORT 8888
struct fdc_info
{
struct sockaddr_in addr;
int fdc;
};
void* dowork(void *arg)//
{
struct fdc_info* info = (struct fdc_info*)arg;
char clit_ip[1024];
char buf[BUFSIZ];
bzero(buf,sizeof(char)*BUFSIZ);
printf("client ip:%s,port:%d
",
inet_ntop(AF_INET,&info->addr.sin_addr.s_addr,clit_ip,1024),
ntohs(info->addr.sin_port));
while(1)
{
int ret = read(info->fdc,buf,sizeof(buf));
if(ret == 0)
{
printf("client %d exit...
",ntohs(info->addr.sin_port));
break;
}
write(STDOUT_FILENO,buf,ret);
for(int i=0;i<ret;++i)
{
buf[i] = toupper(buf[i]);
}
write(info->fdc,buf,ret);
}
Close(info->fdc);
return (void*)0;//pthread_exit();
}
void server_thread()
{
int fds = 0;
//int fdc = 0;
struct sockaddr_in serv_addr,clit_addr;
socklen_t clit_addr_len;
struct fdc_info fdis[256];
bzero(&serv_addr,sizeof(serv_addr));
bzero(&clit_addr,sizeof(clit_addr));
bzero(&fds,sizeof(struct fdc_info)*256);
clit_addr_len = sizeof(clit_addr);
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
fds = Socket(AF_INET,SOCK_STREAM,0);
int opt = 1;//
Setsockopt(fds,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(opt));
Bind(fds,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
Listen(fds,128);
int i = 0;
while (i<256)
{
int fdc = Accept(fds,(struct sockaddr*)&clit_addr,&clit_addr_len);
fdis[i].addr = clit_addr;
fdis[i].fdc = fdc;
pthread_t pd;
pthread_create(&pd,NULL,dowork,&fdis[i]);
pthread_detach(pd);//
++i;
}
Close(fds);
}
int main(int args,char *argc[])
{
server_thread();
return 0;
}
テスト:
nc 127.0.0.1 8888
コマンドを使用して接続を作成し、複数の端末をオープンしてテストできます.