ネットワークプログラミング:マルチスレッド同時サーバー


考え方:ループ待機接続、接続に成功した後、サブスレッドを作成して接続のデータ通信を処理し、メインスレッドは接続を待機し続けます.ソケットインタフェースパッケージ:
#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コマンドを使用して接続を作成し、複数の端末をオープンしてテストできます.