私は、サーバのデーモンがTCPのunixドメイン/ローカルソケットでリッスンしています。同じマシン上で実行されている複数のクライアントが接続しています。デーモンはUDPインターネットソケットにもバインドされています。デーモンは、ローカルクライアントのいずれかからデータを受信するたびに、送信クライアント以外のすべての接続されたクライアントに同じデータを送信します。デーモンがUDPインターネットソケットでデータを受信する場合、デーモンはそのデータをすべてのローカル接続クライアントに送信する必要があります。デーモンがローカルソケット上のデータを受信すると、データの送受信は完全に機能します。ただし、サーバーがUDPインターネットソケットで受信したデータを送信すると、クライアントはデータを受信しません。クライアントは、サーバーデーモンが終了して接続が閉じられた後、またはいずれかのクライアントがサーバーにローカルにデータを送信したときに、インターネットデータを受信します。インターネットデータは、ローカルデータとともにクライアントによって受信される。 fcntl()
を使用して、ローカルソケットとインセットソケットの両方をブロックとして設定しました。ここで私が持っているデーモン・コードは(私はすべての不要なコードを削除した)である:ソケットrecv()はデータを受信しません
while(1)
{
FD_SET(sockfd, &read_fds);
FD_SET(inet_sock, &read_fds);
for (i = 0; i < nclients; i++)
{
FD_SET(clients[i], &read_fds);
}
select(maxfd + 1, &read_fds, &write_fds, &except_fds, NULL);
/* Check for events on inet sock */
if (FD_ISSET(inet_sock, &read_fds))
{
/* Read from inet sock */
socklen = sizeof(dest_sin);
rval = recvfrom(inet_sock, buf, BUFLEN-1, MSG_DONTWAIT,
(struct sockaddr *) &dest_sin, &socklen);
buf[rval]=0;
fprintf(stderr, "Received: %d (%d) bytes containing %s", rval, strlen(buf), buf);
/* Send the message to every other client */
for(j=0; j < nclients; j++)
{
send(clients[j], buf, strlen(buf), MSG_DONTWAIT);
}
}
/* A read event on the local socket is a new connection */
if (FD_ISSET(sockfd, &read_fds))
{
socklen = sizeof(dest_sun);
/* Accept the new connection */
rval = accept(sockfd, (struct sockaddr *) &dest_sun, &socklen);
/* Add client to list of clients */
clients[nclients++] = rval;
if (rval > maxfd) maxfd = rval;
snprintf(s, BUFLEN, "You are client %d [%d]. You are now connected.\n\0",
nclients, rval);
send(rval, s, strnlen(s, BUFLEN), MSG_DONTWAIT);
}
/* Check for events from each client */
for (i = 0; i < nclients; i++)
{
fprintf(stderr,"Checking client %d [%d] for read indicator.\n",i, clients[i]);
/* Client read events */
if (FD_ISSET(clients[i], &read_fds))
{
fprintf(stderr, "Client %d [%d] marked for read.\n", i, clients[i]);
/* Read from client */
rval=recv(clients[i], buf, BUFLEN-1, MSG_DONTWAIT);
buf[rval]=0;
fprintf(stderr, "Received: %d (%d) bytes containing %s", rval, strlen(buf), buf);
/* Send the message to every other client */
for(j=0; j < nclients; j++)
{
/* Skip the sender */
if (j == i) continue;
/* Send the message */
send(clients[j], s, strlen(s, BUFLEN), MSG_DONTWAIT);
}
}
}
}
ここで私が持っているクライアントコードは次のとおりです。
while(1)
{
FD_SET(fileno(stdin), &read_fds);
FD_SET(sockfd, &read_fds);
select(fileno(stdin) > sockfd ? fileno(stdin)+1 : sockfd+1,
&read_fds, &write_fds, &except_fds, NULL);
if (FD_ISSET(sockfd, &read_fds))
{
/* Read from socket and display to user */
mlen = recv(sockfd, (void *)buf, BUFLEN-1, MSG_DONTWAIT);
buf[mlen]=0;
printf("Received %d bytes: %s", mlen, buf);
}
if (FD_ISSET(fileno(stdin), &read_fds))
{
fgets(buf, BUFLEN, stdin);
fprintf(stderr, "Sent %d octets to server.",
send(sockfd, (void *)buf, (size_t) strnlen(buf, BUFLEN), 0));
}
}
目標は、クライアントがデータを受信することですデーモンはそれらを送信します(デーモンがinetソケットで受け取るデータ)。
EDIT:デーモンがデータを送信すると、クライアント側のselect()はソケットが読み込み可能だが、recv()がブロックされていると判断したため、データが表示されません。クライアント側。どのようにこれを修正するための任意の提案?
send(clients[j], buf, strlen(buf), MSG_DONTWAIT);
send(rval, s, strnlen(s, BUFLEN), MSG_DONTWAIT);
send(clients[j], s, strlen(s, BUFLEN), MSG_DONTWAIT);
私はここにいくつかの矛盾を参照してください。ここで
何も飛び出さないうちに、フォームの問題と同じように、printf()文の中でsend()を発行しないでください。また、あなたはコードを削除したと言いました。実際の動作例でコードがエラーコードを返しますか? – Duck
はい、実際のプログラムはエラーチェックを行います。 – ddd
私に飛びつくことは、 'send'と' recv'呼び出しの戻り値を決してチェックしないことです。また、サーバーとクライアントの両方で、どのようにUDPソケットを作成しますか? –