プロが教えるわが家の防犯対策術!

現在、複数のクライアントからサーバーにメッセージを送りサーバーからクライアントにメッセージを送るというものを作成しているのですが、クライアントからサーバーにはメッセージを送れるのですが、サーバー側からクライアント1人にしか送れず、クライアント全員にメッセージを送信できませんので、よろしければアドバイスをお願いします
サーバーのプログラム
インクルード省略
#define BUF_LEN 256
typedef struct CLIENT_INFO {
char hostname[BUF_LEN];
char ipaddr[BUF_LEN];
int port;
time_t last_access;
} CLIENT_INFO;

CLIENT_INFO client_info[FD_SETSIZE];
int listening_socket;
struct sockaddr_in sn;

int
accept_new_client(int sock){
int len;
int new_socket;

struct hostent *peer_host;
struct sockaddr_in peer_sin;

len = sizeof(sn);
new_socket = accept(listening_socket, (struct sockaddr *)&sn, &len);

if ( new_socket == -1 ){
perror("accept");
exit(1);
}

if ( new_socket > FD_SETSIZE-1 ){
return -1;
}
len = sizeof(peer_sin);
getpeername(new_socket,
(struct sockaddr *)&peer_sin, &len);

peer_host = gethostbyaddr((char *)&peer_sin.sin_addr.s_addr,
sizeof(peer_sin.sin_addr), AF_INET);

strncpy(client_info[new_socket].hostname, peer_host->h_name,
sizeof client_info[new_socket].hostname);

strncpy(client_info[new_socket].ipaddr, inet_ntoa(peer_sin.sin_addr),
sizeof client_info[new_socket].ipaddr);

client_info[new_socket].port = ntohs(peer_sin.sin_port);

time(&client_info[new_socket].last_access);

printf("接続: %s (%s) ポート %d ディスクリプタ %d 番\n",
client_info[new_socket].hostname,
client_info[new_socket].ipaddr,
client_info[new_socket].port,
new_socket);
return new_socket;
}
int
read_and_reply(int sock){
int read_size;
char buf[BUF_LEN];

read_size = read(sock, buf, sizeof(buf)-1);

if ( read_size == 0 || read_size == -1 ){
printf("%s (%s) ポート %d ディスクリプタ %d 番からの接続が切れました。\n",
client_info[sock].hostname,
client_info[sock].ipaddr,
client_info[sock].port,
sock);
close(sock);
client_info[sock].last_access = 0;
} else {

buf[read_size] = '\0';
printf("%s (%s) ポート %d ディスクリプタ %d 番からのメッセージ: %s",
client_info[sock].hostname,
client_info[sock].ipaddr,
client_info[sock].port,
sock,
buf);
write(sock, buf, strlen(buf));
time(&client_info[sock].last_access);
}
return read_size;
}
int
main(){
fd_set target_fds;
fd_set org_target_fds;
int sock_optval = 1;
int port = 5000;
 
 listening_socket = socket(AF_INET, SOCK_STREAM, 0);
if ( setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR,
&sock_optval, sizeof(sock_optval)) == -1 ){
perror("setsockopt");
exit(1);
}
 sn.sin_family = AF_INET;
sn.sin_port = htons(port);
sn.sin_addr.s_addr = htonl(INADDR_ANY);

if ( bind(listening_socket, (struct sockaddr *)&sn, sizeof(sn)) < 0 ){
perror("bind");
exit(1);
}
  if ( listen(listening_socket, SOMAXCONN) == -1 ){
perror("listen");
exit(1);
printf("ポート %d を見張ります。\n", port);
  FD_ZERO(&org_target_fds);
FD_SET(listening_socket, &org_target_fds);
  while (1){
int i;
time_t now_time;
struct timeval waitval;
waitval.tv_sec = 2;
waitval.tv_usec = 500;
 memcpy(&target_fds, &org_target_fds, sizeof(org_target_fds));
 select(FD_SETSIZE, &target_fds, NULL, NULL, &waitval);
 for ( i=0 ; i<FD_SETSIZE ; i++ )
{
if ( FD_ISSET(i, &target_fds) )
{
printf("ディスクリプタ %d 番が読み込み可能です。\n", i);
if ( i == listening_socket )
{
int new_sock;
new_sock = accept_new_client(i);
if ( new_sock != -1 )
{
FD_SET(new_sock, &org_target_fds);
}
} else
{int read_size;
 read_size = read_size;
read_size = read_and_reply(i);
if ( read_size == -1 || read_size == 0 )
{
FD_CLR(i, &org_target_fds);
}
}
}
}
time(&now_time);
for ( i=0 ; i<FD_SETSIZE ; i++){
if ( ! FD_ISSET(i, &org_target_fds) ) continue;
if ( i == listening_socket ) continue;
if ( now_time-60 > client_info[i].last_access )
{
close(i);
FD_CLR(i, &org_target_fds);
}
}
}
close(listening_socket);
FD_CLR(i, &org_target_fds);
}
}

A 回答 (2件)

>それではこの列にsend関数をおけば良いのでしょうか?



sendをどう置くつもりですか?(どうすればいいかのヒントは先の回答に書いてます)
writeを置き換えるという事なら全く変わりませんけど。
    • good
    • 0

関数read_and_replyでは、メッセージを送信してきたクライアントに対してしか送信してないので、その他のクライアントにはメッセージが送信されないのは当然では?接続しているクライアント全てに送信したいのならacceptしたソケット全てに対して送信しないと。



他、気になった点
・strncpyは、指定した長さ分コピーした場合にはコピー先に'\0'は付きません。
・TCPで通信を行う場合、送信(writeなど)1回分が、受信(readなど)1回になるとは限りません。複数回に分割されて受信になる事もありますし複数回の送信が1回で受信されることもあります。

この回答への補足

回答ありがとうございます。確認したところ確かにread_and_replyではダメですね。
それではこの列にsend関数をおけば良いのでしょうか?

補足日時:2013/02/06 00:24
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!