質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.64%

C言語 マルチスレッドを用いたソケット

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 3,896

shanso

score 14

server2.c:154: 警告: implicit declaration of function ‘mystrlcat’
/tmp/cckhwOW7.o: In function `send_recv_thread':
server2.c:(.text+0x4ea): undefined reference to `mystrlcat'
collect2: ld はステータス 1 で終了しました

というエラーがコンパイル時に出ますが原因が分かりません
助力お願いします

#include<sys/param.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<netdb.h>
#include<ctype.h>
#include<errno.h>
#include<pthread.h>
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sysexits.h>
#include<unistd.h>


int server_socket(const char *portnm)
{
 char nbuf[NI_MAXHOST],sbuf[NI_MAXSERV];
 struct addrinfo hints, *res0;
 int soc,opt,errcode;
 socklen_t opt_len;
 
 (void) memset(&hints,0,sizeof(hints));
 hints.ai_family=AF_INET;
 hints.ai_socktype=SOCK_STREAM;
 hints.ai_flags=AI_PASSIVE;
 
 //アドレス情報の決定
 if((errcode=getaddrinfo(NULL,portnm,&hints,&res0))!=0)
 {
   (void) fprintf(stderr,"getaddrinfo():%s\n",gai_strerror(errcode));
   return (-1);
 }
 
 if((errcode=getnameinfo(res0->ai_addr,res0->ai_addrlen,
                            nbuf,sizeof(nbuf),
                            sbuf,sizeof(sbuf),
                            NI_NUMERICHOST | NI_NUMERICSERV))!=0)
 {
  (void)fprintf(stderr,"getnameinfo():%s\n",gai_strerror(errcode));
  freeaddrinfo(res0);
  return (-1);
 }
  (void) fprintf(stderr,"port=%s\n",sbuf);
  
  //ソケットの作成
  if((soc=socket(res0->ai_family,res0->ai_socktype,res0->ai_protocol))==-1)
  {
   perror("socket");
   freeaddrinfo(res0);
   return (-1);
  }
//ソケットオプション(再利用フラグ)設定
 opt=1;
 opt_len=sizeof(opt);
 if(setsockopt(soc,SOL_SOCKET,SO_REUSEADDR,&opt,opt_len)==-1)
 {
   perror("setsockopt");
   (void) close(soc);
   freeaddrinfo(res0);
   return -1;
 }
 
 //ソケットにアドレスを指定
 if(bind(soc,res0->ai_addr,res0->ai_addrlen)==-1)
 {
  perror("bind");
  (void) close(soc);
  freeaddrinfo(res0);
  return (-1);
 }
 
 //アクセスバックログの指定
 if(listen(soc,SOMAXCONN)==-1)
 {
  perror("listen");
  (void) close(soc);
  freeaddrinfo(res0);
  return (-1);
  }
  freeaddrinfo(res0);
  return (soc);
 }
 
 //アクセプトループ
 void accept_loop(int soc)
 {
   char hbuf[NI_MAXHOST],sbuf[NI_MAXSERV];
   struct sockaddr_storage from;
   int acc;
   socklen_t len;
   pthread_t thread_id;
   void *send_recv_thread(void *arg);
   
   for(;;){
      len=(socklen_t)sizeof(from);
      
      //接続受付
      if((acc=accept(soc,(struct sockaddr *)&from,&len))==-1){
          if(errno!=EINTR){
             perror("accept");
             }
           }else{
           (void)getnameinfo((struct sockaddr *)&from,len,
                                  hbuf,sizeof(hbuf),
                                  sbuf,sizeof(sbuf),
                                  NI_NUMERICHOST | NI_NUMERICSERV);
   
   (void)fprintf(stderr,"accept:%s:%s\n",hbuf,sbuf);
   
   //スレッド作成
   if(pthread_create(&thread_id,NULL,send_recv_thread,(void *)acc)!=0){
      perror("pthread_create");
      }else{
      (void)fprintf(stderr,"pthread_create:create:thread_id=%d\n",(int)thread_id);
      }
    }
  }
}

//送受信スレッド
 void * send_recv_thread(void *arg)
 {
  char buf[512],*ptr;
  ssize_t len;
  int acc;
  
  //スレッドのデタッチ
  (void)pthread_detach(pthread_self());
  //引数の取得
  acc=(int)arg;
  for(;;){
  //受信
  if((len=recv(acc,buf,sizeof(buf),0))==-1){
  //エラー
  perror("recv");
  break;
  }
  if(len==0){
  //エンドオブファイル
  (void)fprintf(stderr,"<%d>recv:EOF\n",(int)pthread_self());
  break;
  }
  //文字列化・表示
  buf[len]='\0';
  if((ptr=strpbrk(buf,"\r\n"))!=NULL){
  *ptr='\0';
  }
  (void)fprintf(stderr,"<%d>[client]%s\n",(int)pthread_self(),buf);
  //応答文字列作成
  (void)mystrlcat(buf,":OK\r\n",sizeof(buf));
  len=(ssize_t) strlen(buf);
  //応答
  if((len=send(acc,buf,(size_t)len,0))==-1){
  //エラー
  perror("send");
  break;
  }
 }
 (void)close(acc);
 pthread_exit((void *) 0);
 
 //NOT REACHED
 return ((void *) 0);
 }
 
 int main(int argc, char *argv[])
{
 int soc;
 
 //引数にポート番号が指定されているか
 if(argc<=1)
 {
  (void)fprintf(stderr,"server port\n");
  return (EX_USAGE);
 }
 
 //サーバソケットの準備
 if((soc=server_socket(argv[1]))==-1)
 {
  (void)fprintf(stderr,"server_socket(%s):error\n",argv[1]);
  return (EX_UNAVAILABLE);
 }
 (void) fprintf(stderr,"ready for accept\n");
 
 //アクセプトループ
 accept_loop(soc);
 //ソケットクローズ
 (void) close(soc);
 return (EX_OK);
 }

  

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • argius

    2015/10/23 11:45

    すみません、聞き方が良くなかったですね。mystrlcatの関数の宣言箇所はどこでしょうか?

    キャンセル

  • shanso

    2015/10/23 11:46

    宣言を忘れていますね
    ありがとうございました

    キャンセル

  • argius

    2015/10/23 11:49

    解決してしまいましたか? お手数ですが自己解決にしちゃってください。

    キャンセル

回答 1

check解決した方法

0

宣言を忘れていました
お手数おかけして申し訳ありません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る