シンプルなソケットサーバーを作成しようとしていますが、この例ではエコーサーバーです。なぜ「選択」しても「受け入れる」必要があると思われますか?
これは私のメインプログラムに続いてsocket_server.c(それが立ち往生場所についてのコメントを注意してください)
int fdmax, i, socket_descriptor;
fd_set master, read_fds;
struct timeval tv = {.tv_sec = 0, .tv_usec = 1000};
void socket_server_init(void)
{
FD_ZERO(&master);
FD_ZERO(&read_fds);
}
socket_server_socket socket_server_start(char *socket_path)
{
struct sockaddr_un local;
int len;
int socket_descriptor = socket(AF_UNIX, SOCK_STREAM, 0);
if (socket_descriptor == -1)
return (socket_server_socket) {.status = SOCKET_SERVER_START_SOCKET_FAILURE, .descriptor = -1};
local.sun_family = AF_UNIX;
strcpy(local.sun_path, socket_path);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(socket_descriptor, (struct sockaddr *)&local, len) == -1)
return (socket_server_socket) {.status = SOCKET_SERVER_START_BIND_FAILURE, .descriptor = -1};
if (listen(socket_descriptor, 5) == -1)
return (socket_server_socket) {.status = SOCKET_SERVER_START_LISTEN_FAILURE, .descriptor = -1};
FD_SET(socket_descriptor, &master);
fdmax = socket_descriptor;
return (socket_server_socket) {.status = 0, .descriptor = socket_descriptor};
}
socket_server_socket socket_server_wait_for_connection(socket_server_socket server)
{
read_fds = master;
select(fdmax+1, &read_fds, NULL, NULL, &tv);
for (i = 0; i <= fdmax; i++)
{
if (FD_ISSET(i, &read_fds))
{
if (i == server.descriptor)
{
// It's getting stuck here.
socket_descriptor = accept(server.descriptor, (struct sockaddr *) NULL, NULL);
if (socket_descriptor > fdmax)
fdmax = socket_descriptor;
FD_SET(socket_descriptor, &master);
return (socket_server_socket) {.status = -1, .descriptor = socket_descriptor};
} else {
return (socket_server_socket) {.status = 0, .descriptor = i};
}
}
}
return (socket_server_socket) {.status = -1, .descriptor = -1};
}
int socket_server_update(socket_server_socket client)
{
char buffer[256];
int n = recv(client.descriptor, buffer, 256, 0);
if (n < 0)
return SOCKET_SERVER_UPDATE_RECV_FAILURE;
if (send(client.descriptor, buffer, n, 0) < 0)
return SOCKET_SERVER_UPDATE_SEND_FAILURE;
close(client.descriptor);
return 0;
}
です:
:私は、私が観察し、プログラムを実行するとsocket_server_init();
socket_server_socket server = socket_server_start(SOCKET_PATH);
while (1) {
printf("wait for conn\n");
socket_server_socket client = socket_server_wait_for_connection(server);
if (client.status == 0)
{
socket_server_update(client);
}
sleep(1);
printf("%d: Log !\n", (int)time(NULL));
}
- "ログ!"コンソールから出力されます
- ソケットを介してサーバーに接続します
- "ログ!"コンソール
- に私は
- クライアントがデータを
- エコーバック見ているクライアントからのいくつかのデータを送信し、「ログ!」もはやクライアントからのそれ以降のデータはバック
エコーされませんコンソール
accept
呼び出しで停止しているように見えますが、2回目です。 私が理解しているように、select
は、受け入れるかrecvする必要がある場合にのみ、read_fds
に記述子を追加することになっています。そうaccept
編accept
なるのを待っているものは何もありませんread_fds
select
を受け入れますread_fds
select
:だから何がある発生するようですハングします
私が確認したのは、accept
呼び出しに達すると、記述子は同じです。だから私は非常に混乱しています。
私は間違っていますか?私は同じ接続のためにもう一度accept
を打つべきではないと確信しています。
これは近いと思われます...私はあなたの提案に従うことができません。なぜなら、接続を待つ間にselectをブロックするためです。私はタイムアウトを使用していますので、私のプログラムの他の部分は引き続き作業できます。私は 'if(select(fdmax + 1、&read_fds、NULL、NULL、&tv)<0)return;'を試しましたが、 'select'が何らかの理由で-1を返すという状況に陥ります。 –
あなたの 'fd_set'から無効なソケットを' FD_CLR'する必要があることに注意してください。 。単純なチャットのためにbeejの例に従ってみて、あなたのプログラムと比較してみてください。 selectが-1を返す理由を調べるには、最後のエラーを 'perror'で表示してみてください。 –
@CameronBall selectが0を返した場合、タイムアウトが発生しています。それが<0を返す場合は、エラー*があり、エラーが何であるかを調べるには、errnoをチェックしたり、perrorを使用する必要があります。 –