Ubuntu 10.10 + gcc4.4 + eclipse で C言語プログラミングをしています。
ソケットを使用したプログラムを試していたのですが、思うように動作しません。
作成したプログラムは以下のようなものです。
・ローカルマシン上で、サーバプログラム、クライアントプログラムを用意する
・サーバ側はソケット作成後、クライアントが接続するまで listen する
・クライアントはサーバに接続したら、接続した旨を表示する
という初歩的なものです。
問題は、サーバ側が accept したときに戻り値 -1 を返却して終了してしまうことです。
以下が作成したソースです。
■■■▼ サーバ側ここから ▼■■■
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_un srv;
socklen_t socklen;
/* ソケット名をコマンド入力で受け取る */
if(argc != 2) {
puts("USAGE: mksock <filename>");
exit(EXIT_FAILURE);
}
/* ソケット作成 */
if((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0){
exit(EXIT_FAILURE);
}
/* srv 初期化 */
memset(&srv, 0, sizeof(srv));
srv.sun_family = AF_UNIX;
strncpy(srv.sun_path, argv[1], sizeof(srv.sun_path));
/* バインド */
if((bind(sockfd, (struct sockaddr *)&srv, SUN_LEN(&srv))) < 0){
exit(EXIT_FAILURE);
}
/* クライアントからの接続待ち */
if((listen(sockfd, 5)) < 0) {
exit(EXIT_FAILURE);
}
printf("socket available: %s, sockfd=%d\n", srv.sun_path, sockfd);
/* 接続がある限りくりかえす */
int sockResult;
while(1) {
sockResult = accept(sockfd, (struct sockaddr *)&srv, &socklen);
printf("sockResult = %d, sun_path=%s\n", sockResult, srv.sun_path);
if (sockResult < 0)
break;
puts("new connection granted");
}
puts("mksock end");
exit(EXIT_SUCCESS);
}
■■■▲ サーバ側ここまで ▲■■■
●●●▼ クライアント側ここから ▼●●●
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_un cli;
socklen_t socklen;
/* ソケット名をコマンド入力で受け取る */
if(argc != 2) {
puts("USAGE: sockconn <filename>");
exit(EXIT_FAILURE);
}
/* ソケット作成 */
if((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0){
exit(EXIT_FAILURE);
}
/* クライアント設定 */
memset(&cli, 0, sizeof(cli));
cli.sun_family = AF_UNIX;
strncpy(cli.sun_path, argv[1], sizeof(cli.sun_path));
/* サーバへ接続 */
socklen = SUN_LEN(&cli);
if(connect(sockfd, (struct sockaddr *)&cli, socklen)) {
exit(EXIT_FAILURE);
}
printf("connected to socket %s\n", cli.sun_path);
exit(EXIT_SUCCESS);
}
●●●▲ クライアント側ここまで ▲●●●
これから作成されたバイナリを同一フォルダに置いて、作成ユーザで、カレントディレクトリで実行しました。
以下が実行時の入出力です(カッコ内は実行順序)。
■▼ サーバ側ここから ▼■
$ ./mksock jjj1…(1)
$ socket available: jjj1, sockfd=3
$ sockResult = -1, sun_path=jjj1
$ mksock end
■▲ サーバ側ここから ▲■
●▼ クライアント側ここから ▼●
$ ./sockconn jjj1…(2)
$ connected to socket jjj1
●▲ クライアント側ここから ▲●
上記のように、サーバ側が accept 時に -1 を返却しています。
パーミッションについては以下になっています。
srwxr-xr-x 1 hoge hoge 0 2011-09-04 21:36 jjj1
-rwxr--r-- 1 hoge hoge 86870 2011-09-04 21:36 mksock
-rwxr--r-- 1 hoge hoge 86775 2011-09-04 21:36 sockconn
パーミッションを見る限り、ソケットファイルにはアクセスできているかと。
おそらく環境周りではないかと思いますが、考えつきません。
linux プログラミングに詳しいかた、よろしくお願いいたします。
No.1ベストアンサー
- 回答日時:
こちら、CentOS release 5.6 (Final)
で確認しましたところ、正常に動作しました。
(new connection grantedのメッセージが表示されました。)
>おそらく環境周りではないかと思いますが、考えつきません。
こちらで、再現しないので、環境の問題かと思います。
原因を特定するために、errnoを印字して確認しては、いかがですか。
(必ずしも特定できることが保障されるわけではありませんが・・・)
以下のようにしてください。
printf("sockResult = %d, sun_path=%s,errno=%d\n", sockResult, srv.sun_path,errno);
アドバイスありがとうございました。
おかげで動作するところまでたどり着きました!
以下の手順で調査しました。
(1)アドバイスどおり errno を出力するようにして実行
$ sockResult = -1, sun_path=aaa, errno=22
(2)errno=22 は EINVAL ということだったので、accept の man より「ソケットが接続待ち状態ではない。もしくは、 addrlen が不正である」と判明
(3) 確かに accept の引数の socklen に値を代入していなかったので、srv を sizeof して代入
socklen = sizeof(srv);
(4)実行したら成功!
$ sockResult = 4, sun_path=aaa, errno=0
$ new connection granted
ただ、こちらでも CentOS で動かしてみたら、確かに修正前のソースでも動作しました。
gcc のバージョンか、ディストリの違いによるのか(?)分からないのが気持ちが悪いですが。。。。
いずれにせよ、これで errno の使い方もわかりました。
ありがとうございました!
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# 並列プログラミングのπ計算について 1 2022/07/16 22:30
- C言語・C++・C# C言語のファイル入力が分かりません 2 2022/05/22 06:35
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- JavaScript 1日1回引けるJavaScriptおみくじについて 1 2022/12/12 22:28
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
TCP/IP通信時のサーバーからの受信
-
UDP通信におけるbind関数について
-
WinSockでの通信プログラムがう...
-
C#とTCP/IPを利用したサーバー...
-
ソケット通信 同じポート番号...
-
winsockでファイル転送
-
Winsockで接続待ちタイムアウト...
-
Socket通信の0バイト受信について
-
POP3S
-
どうか、POSTでのファイル転送...
-
UDP通信する時に、相手にどうや...
-
fsockopenのソケットが全然分か...
-
SIPがNATを越えられない理由
-
Linuxのsocket接続でacceptでき...
-
空きポートの取得方法
-
Winsockプログラムの初歩的質問...
-
エクセル VBA でのCOMポート...
-
VB6のwinsockでconnectできない
-
ソケットを用いた1対多通信につ...
-
相手のIPアドレスを取得する方法
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
TCP/IP通信時のサーバーからの受信
-
recv関数でフリーズしてしまう
-
Winsockで接続待ちタイムアウト...
-
UDP通信におけるbind関数について
-
エクセル VBA でのCOMポート...
-
Socket通信の0バイト受信について
-
VB6のwinsockでconnectできない
-
ソケットのrecvの戻り値が0
-
ソケットを用いた1対多通信につ...
-
UdpClient 送信元のIPアドレ...
-
ソケットでクライアントのipア...
-
UDP通信する時に、相手にどうや...
-
ソケット通信 同じポート番号...
-
同じLAN内パソコンのIPアドレス...
-
Connectエラーが出てしまう・・...
-
ソケットのクローズについて
-
CreateFile関数でCOMポートが開...
-
異なる言語間でのソケット通信...
-
C言語でHTTP1.1のキープアライ...
-
送信したデータの一部が文字化...
おすすめ情報