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

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

新規登録して質問してみよう
ただいま回答率
85.48%
CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

マルチスレッド

マルチスレッドは、どのように機能がコンピュータによって実行したのかを、(一般的にはスレッドとして参照される)実行の複合的な共同作用するストリームへ区分することが出来ます。

Q&A

解決済

1回答

6620閲覧

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

shanso

総合スコア14

CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

マルチスレッド

マルチスレッドは、どのように機能がコンピュータによって実行したのかを、(一般的にはスレッドとして参照される)実行の複合的な共同作用するストリームへ区分することが出来ます。

0グッド

0クリップ

投稿2015/10/23 02:27

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);
}

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

argius

2015/10/23 02:36

mystrlcatはどこに書いていますか?
shanso

2015/10/23 02:42

//送受信スレッド void * send_recv_thread(void *arg) の中の応答文字列作成のところです
argius

2015/10/23 02:45

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

2015/10/23 02:46

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

2015/10/23 02:49

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

回答1

0

自己解決

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

投稿2015/10/23 02:56

shanso

総合スコア14

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問