前提・実現したいこと
POSIXスレッドを使用しクライアントpcからの入力内容をそのまま返すエコーサーバの並列通信を実装しようとしています。
接続要求を待ち,通信用のソケットを作成するacceptまでは処理が完了していると思われるのですが、その後の通信用ソケットディスクリプタ、クライアント番号、アドレス構造体を構造体へセットする際(コメント部2)にsegmentation fault 11のコアダンプを起こしていると思われます。該当する部分の順番を替えたりしてみたのですが同じくコアダンプが起きてしまいます。
発生している問題・エラーメッセージ
Segmentation fault (コアダンプ)
該当のソースコード
c
1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#include <unistd.h> 5#include <sys/socket.h> 6#include <netinet/in.h> 7#include <arpa/inet.h> 8#include <sys/types.h> 9#include <pthread.h> 10#define BUFSIZE 1024 11#define LISTENQ 1024 12 13void *thread(void *arg); 14 15struct ThreadArgs { 16 int sock; 17 int cnt; 18 struct sockaddr_in sa; 19}; 20 21int main(int argc, char *argv[]){ 22 int listen_sock, comm_sock, sa_len, cnt; 23 struct sockaddr_in sa, new_sa; 24 pthread_t thread_id; 25 struct ThreadArgs *args; 26 listen_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 27 int option = 1; 28 setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); 29 memset(&sa, 0, sizeof(sa));ここに問題に対して試したことを記載してください。 30 sa.sin_family = AF_INET; 31 sa.sin_port = htons(49152); 32 sa.sin_addr.s_addr = htonl(INADDR_ANY); 33 if(bind(listen_sock, (struct sockaddr *)&sa, sizeof(sa)) < 0){ 34 fprintf(stderr, "bind() failure\n"); 35 exit(1); 36 } 37 if(listen(listen_sock, LISTENQ) < 0){ 38 fprintf(stderr, "listen() failure\n"); 39 exit(1); 40 } 41 cnt = 0; 42 while(1){ 43 printf("Waiting for a client\n"); 44 sa_len = sizeof(new_sa); 45 if((comm_sock = accept(listen_sock, (struct sockaddr *)&new_sa, &sa_len)) < 0){ 46 fprintf(stderr, "accept() failure\n"); 47 exit(1); 48 } 49 ++cnt; 50 // 1. 引数用の構造体のメモリを確保する 51 args = (struct ThreadArgs *)malloc(sizeof(struct ThreadArgs)); 52 if(args = NULL){ 53 fprintf(stderr, "malloc() failure\n"); 54 exit(1); 55 } 56/*ここまでは処理できている模様*/ 57 58 // 2. 通信用ソケットディスクリプタ,クライアント番号,アドレス構造体を確保した構造体にセット 59 args->sock = comm_sock; 60 args->cnt = cnt; 61 args->sa = sa; 62 // 3. pthread_create()でスレッドを作成 63 if(pthread_create(&thread_id, NULL, (void *)thread, (void *)args) != 0){ 64 fprintf(stderr, "pthread_create() failure\n"); 65 exit(1); 66 } 67 } 68 return 0; 69} 70 71void *thread(void *arg){ 72 int sock, cnt, n, msg_len; 73 struct sockaddr_in sa; 74 char buf[BUFSIZE]; 75 pthread_detach(pthread_self()); 76 // 4. arg から通信用ソケットディスクリプタ,クライアント番号,アドレス構造体を取得し,それぞれ sock, cnt, sa にセット 77 sock = ((struct ThreadArgs *)arg)->sock; 78 cnt = ((struct ThreadArgs *)arg)->cnt; 79 sa = ((struct ThreadArgs *)arg)->sa; 80 printf("Client %d (%s) connected\n", cnt, inet_ntoa(sa.sin_addr)); 81 if((n = recv(sock, buf, sizeof(buf), 0)) > 0){ 82 buf[n] = '\0'; 83 msg_len = strlen(buf); 84 printf("Client %d: %s\n", cnt, buf); 85 if(send(sock, buf, msg_len, 0) != msg_len){ 86 fprintf(stderr, "send() failure\n"); 87 } 88 } 89 close(sock); 90 printf("Client %d disconnected\n", cnt); 91 free(arg); 92}
試したこと
試すというほどの事ではないのですが該当箇所の型があっているかの確認はしました。
参考にしたプログラム
上がスレッド実装前のエコーサーバプログラム
下がスレッドのみを実装し、それぞれのスレッドで数秒ごとに1~10をカウントするプログラム
c
1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#include <unistd.h> 5#include <sys/socket.h> 6#include <netinet/in.h> 7#include <arpa/inet.h> 8#include <sys/types.h> 9#define BUFSIZE 1024 10#define LISTENQ 1024 11int main(int argc, char *argv[]) 12{ 13 int listen_sock, comm_sock, msg_len, sa_len, cnt, n; 14 struct sockaddr_in sa, new_sa; 15 char buf[BUFSIZE]; 16 listen_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 17 memset(&sa, 0, sizeof(sa)); 18 sa.sin_family = AF_INET; 19 sa.sin_port = htons(49152); // 49152番ポートで待ち受ける 20 sa.sin_addr.s_addr = htonl(INADDR_ANY); // どんなIPアドレスからでもOK 21 if(bind(listen_sock, (struct sockaddr *)&sa, sizeof(sa)) < 0){ 22 fprintf(stderr, "bind() failure\n"); 23 exit(1); 24 } 25 if(listen(listen_sock, LISTENQ) < 0){ 26 fprintf(stderr, "listen() failure\n"); 27 exit(1); 28 } 29 cnt = 1; 30 while(1){ 31 printf("Waiting for a client\n"); 32 sa_len = sizeof(new_sa); 33 if((comm_sock = accept(listen_sock, (struct sockaddr *)&new_sa, &sa_len)) < 0){ 34 fprintf(stderr, "accept() failure\n"); 35 exit(1); 36 } 37 38 printf("Client %d (%s) connected\n", cnt, inet_ntoa(new_sa.sin_addr)); 39 while(1){ 40 if((n = recv(comm_sock, buf, sizeof(buf), 0)) > 0){ 41 buf[n] = '\0'; 42 msg_len = strlen(buf); 43 printf("Client %d: %s\n", cnt, buf); 44 if(send(comm_sock, buf, msg_len, 0) != msg_len){ 45 fprintf(stderr, "send() failure\n"); 46 exit(1); 47 } 48 } 49 } 50 close(comm_sock); 51 printf("Client %d disconnected\n", cnt); 52 ++cnt; 53 } 54 return 0; 55}
c
1#include <stdio.h> 2#include <unistd.h> 3#include <stdlib.h> 4#include <pthread.h> 5 6void *thread(void *arg); 7 8struct ThreadArgs{ 9 int sec; 10 char *msg; 11}; 12 13int main(int argc, char *argv[]){ 14 pthread_t thread_id1, thread_id2, thread_id3; 15 struct ThreadArgs *args; 16 17 args = (struct ThreadArgs *)malloc(sizeof(struct ThreadArgs)); 18 if(args == NULL){ 19 fprintf(stderr, "malloc() failure\n"); 20 exit(1); 21 } 22 args->sec = 1; 23 args->msg = "thread1"; 24 if(pthread_create(&thread_id1, NULL, (void *)thread, (void *)args) != 0){ 25 fprintf(stderr, "pthread_create() failure\n"); 26 exit(1); 27 } 28 29 args = (struct ThreadArgs *)malloc(sizeof(struct ThreadArgs)); 30 if(args == NULL){ 31 fprintf(stderr, "malloc() failure\n"); 32 exit(1); 33 } 34 args->sec = 2; 35 args->msg = "thread2"; 36 if(pthread_create(&thread_id2, NULL, (void *)thread, (void *)args) != 0){ 37 fprintf(stderr, "pthread_create() failure\n"); 38 exit(1); 39 } 40 41 args = (struct ThreadArgs *)malloc(sizeof(struct ThreadArgs)); 42 if(args == NULL){ 43 fprintf(stderr, "malloc() failure\n"); 44 exit(1); 45 } 46 args->sec = 3; 47 args->msg = "thread3"; 48 if(pthread_create(&thread_id3, NULL, (void *)thread, (void *)args) != 0){ 49 fprintf(stderr, "pthread_create() failure\n"); 50 exit(1); 51 } 52 53 pthread_join(thread_id1, NULL); 54 pthread_join(thread_id2, NULL); 55 pthread_join(thread_id3, NULL); 56 return 0; 57 } 58 59void *thread(void *arg){ 60 int sec, i; 61 char *msg; 62 sec = ((struct ThreadArgs *)arg)->sec; 63 msg = ((struct ThreadArgs *)arg)->msg; 64 for(i=0; i<10; i++){ 65 sleep(sec); 66 printf("%s %lu: %d\n", msg, pthread_self(), i+1); 67 } 68 free(arg); 69}
回答2件
あなたの回答
tips
プレビュー