Linux C言語 ソケット通信 子スレッドで待ち受けするとbindエラーが出る
閲覧ありがとうございます。
C言語でサーバプログラミングをしています。
実装したいことはサーバーのプログラムでマルチスレッドのスレッドプールというものです。
実装したい内容としては
「子スレッドを5つつくり、この5つで
クライアントからの接続に対応する。」
「5つまでしか接続できない」
「小スレッドは終了させず、接続が切れたら次の接続を待つ」
の3点となります。
マルチスレッドではなく、forkで実装したところ
うまくいったのですが、マルチスレッドではタイトルのように
bindエラーが出て困っているのでお力を貸して頂きたいです。
コード内容は以下の通りです。
#define PRCS_LIMIT 5 /* 小スレッド数制限 */
#define BUFSIZE 50 /* バッファサイズ */
void * execute(void *arg);
int init_tcpserver(in_port_t myport, int backlog);
int main(int argc, char *argv[]) {
int *port_number;
int temp;
pthread_t tid;
temp = atoi(argv[1]);
port_number = &temp;
/* 子スレッドを5つ生成する */
int i;
for (i = 1; i <= PRCS_LIMIT; i++) {
if (pthread_create(&tid, NULL, execute, (void *) port_number) != 0) {
exit_errmesg("pthread_create()");
}
}
//親スレッドは終わらせない。
while(1){
}
return 0;
/* never reached */
}
/* スレッドの本体 */
void * execute(void *arg) {
int sock_accepted;
int sock_listen;
char buf[BUFSIZE];
int strsize;
/* サーバの初期化 */
sock_listen = init_tcpserver(*(int *) arg, 5);
/* クライアントの接続を受け付ける */
sock_accepted = accept(sock_listen, NULL, NULL);
pthread_detach(pthread_self()); /* スレッドの分離(終了を待たない) */
close(sock_listen);
while (1) {
/* 文字列をクライアントから受信する */
send(sock_accepted, ">", 2, 0);
if ((strsize = recv(sock_accepted, buf, BUFSIZE, 0)) == -1) {
exit_errmesg("recv()");
}
if (strstr(buf, "end") != NULL) {
close(sock_accepted);
/* サーバに接続する */
sock_listen = init_tcpserver(*(int *) arg, 5);
/* クライアントの接続を受け付ける */
sock_accepted = accept(sock_listen, NULL, NULL);
}
/* 文字列をクライアントに送信する */
if (send(sock_accepted, buf, strsize, 0) == -1) {
exit_errmesg("send()");
}
}
return (NULL);
}
int init_tcpserver(in_port_t myport, int backlog)
{
struct sockaddr_in my_adrs;
int sock_listen;
int yes = 1;
/* サーバ(自分自身)の情報をsockaddr_in構造体に格納する */
memset(&my_adrs, 0, sizeof(my_adrs));
my_adrs.sin_family = AF_INET;
my_adrs.sin_port = htons(myport);
my_adrs.sin_addr.s_addr = htonl(INADDR_ANY);
/* 待ち受け用ソケットをSTREAMモードで作成する */
if((sock_listen = socket(PF_INET, SOCK_STREAM, 0)) == -1){
exit_errmesg("socket()");
}
//TIME_WAIT状態でもbindできるようにする。
setsockopt(sock_listen, SOL_SOCKET, SO_REUSEADDR, (const char *)&yes, sizeof(yes));
/* 待ち受け用のソケットに自分自身のアドレス情報を結びつける */
if(bind(sock_listen, (struct sockaddr *)&my_adrs, sizeof(my_adrs)) == -1 ){
exit_errmesg("bind()");
}
/* クライアントからの接続を受け付ける準備をする */
if(listen(sock_listen, backlog) == -1){
exit_errmesg("listen()");
}
return(sock_listen);
}