ページ 11

ネットワークプログラミングについて

Posted: 2012年8月01日(水) 23:03
by Rance
サーバのプログラムを、
「クライアントから送られて来た文字列を、エコーサーバに接続しているクライアント全てに送る。」

クライアントのプログラムを、
「サーバから戻ってきた文字列をどのクライアントが送った文字列かをわかるようにする。」

下記のプログラムを上記のように書き直したいのですが、どう書き直せばいいのでしょうか?

コード:

/*
 サーバプログラム
  $ gcc -o echo_server echo_server.c -lpthread
  $ ./echo_server
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <pthread.h>

#define BUFSIZE 1024
#define LISTENQ 1024

void *thread(void *arg);

struct ThreadArgs {
  int sock;
  int cnt;
  struct sockaddr_in sa;
};

int main(int argc, char *argv[])
{
  int listen_sock, comm_sock, sa_len, cnt;
  struct sockaddr_in sa, new_sa;
  pthread_t thread_id;
  struct ThreadArgs *args;

  listen_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

  memset(&sa, 0, sizeof(sa));
  sa.sin_family = AF_INET;
  sa.sin_port = htons(49152);
  sa.sin_addr.s_addr = htonl(INADDR_ANY);

  if (bind(listen_sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
    fprintf(stderr, "bind() failure\n");
    exit(1);
  }

  if (listen(listen_sock, LISTENQ) < 0) {
    fprintf(stderr, "listen() failure\n");
    exit(1);
  }

  cnt = 0;
  while (1) {
    sa_len = sizeof(new_sa);
    if ((comm_sock = accept(listen_sock, (struct sockaddr *)&new_sa, &sa_len)) < 0) {
      fprintf(stderr, "accept() failure\n");
      exit(1);
    }
    ++cnt;

    args = (struct ThreadArgs *)malloc(sizeof(struct ThreadArgs));

    args->sock = comm_sock;
    args->cnt  = cnt;
    args->sa   = new_sa;

    if (pthread_create(&thread_id, NULL, (void *)thread, (void *)args) != 0) {
      fprintf(stderr, "pthread_create() failure\n");
      exit(1);
    }
  }
  return 0;
}

void *thread(void *arg)
{
  int sock, cnt, n, msg_len;
  struct sockaddr_in sa;
  char buf[BUFSIZE];

  if (pthread_detach(pthread_self()) != 0) {
    fprintf(stderr, "pthread_detach() failure\n");
    exit(1);
  }

  struct ThreadArgs *args = arg;
  sock = args->sock;
  cnt  = args->cnt;
  sa   = args->sa;

  printf("Client %d (%s) connected\n", cnt, inet_ntoa(sa.sin_addr));

  if ((n = recv(sock, buf, sizeof(buf), 0)) > 0) {
    buf[n] = '\0';
    msg_len = strlen(buf);
    printf("Client %d: %s\n", cnt, buf);
    if (send(sock, buf, msg_len, 0) != msg_len) {
      fprintf(stderr, "send() failure\n");
      exit(1);
    }
  }
  close(sock);

  printf("Client %d disconnecter\n", cnt);
  printf("\n");

  free(arg);

  return;
}
 

コード:

/*
  クライアントプログラム
  $ gcc -o echo_client echo_client.c
  $ ./echo_client 127.0.0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>

#define MSGSIZE 512
#define BUFSIZE 1024

int main(int argc, char *argv[])
{
  int sock, msg_len, n;
  struct sockaddr_in sa;
  char *server_ip;
  char msg[MSGSIZE], buf[BUFSIZE];

  if (argc != 2) {
    fprintf(stderr, "usage: echo_client SERVER_IP_ADDRESS\n");
    exit(1);
  }
  server_ip = argv[1];

  while (1) {
    sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

    memset(&sa, 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_port = htons(49152);
    sa.sin_addr.s_addr = inet_addr(server_ip);

    if (connect(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
      fprintf(stderr, "connect() failure\n");
      exit(1);
    }

    printf("please input a message!\n");
    printf("> ");
    scanf("%s", msg);
    msg_len = strlen(msg);

    if (send(sock, msg, msg_len, 0) != msg_len) {
      fprintf(stderr, "send() failure\n");
      exit(1);
    }

    if (strcmp(msg, "exit") == 0) {
      exit(1);
    }

    if ((n = recv(sock, buf, sizeof(buf), 0)) > 0) {
      buf[n] = '\0';
      printf("Echo message: ");
      printf("%s\n", buf);
    } else if (n < 0) {
      fprintf(stderr, "recv() failure\n");
      exit(1);
    }
    printf("\n");
    close(sock);
  }

  return 0;
}

Re: ネットワークプログラミングについて

Posted: 2012年8月02日(木) 01:39
by かずま
エラー処理はしていませんが、参考にはなるのでは?

コード:

/*
 サーバプログラム
  $ gcc -o echo_server echo_server.c -lpthread
  $ ./echo_server
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <pthread.h>
 
#define BUFSIZE 1024
#define LISTENQ 1024
 
void *thread(void *arg);
 
struct ThreadArgs {
  int sock;
  int cnt;
  struct sockaddr_in sa;
};
 
struct ThreadArgs *ta[LISTENQ];
int ta_count;

int main(int argc, char *argv[])
{
  int listen_sock, comm_sock, sa_len, cnt;
  struct sockaddr_in sa, new_sa;
  pthread_t thread_id;
  struct ThreadArgs *args;
 
  listen_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 
  memset(&sa, 0, sizeof(sa));
  sa.sin_family = AF_INET;
  sa.sin_port = htons(49152);
  sa.sin_addr.s_addr = htonl(INADDR_ANY);
 
  if (bind(listen_sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
    fprintf(stderr, "bind() failure\n");
    exit(1);
  }
 
  if (listen(listen_sock, LISTENQ) < 0) {
    fprintf(stderr, "listen() failure\n");
    exit(1);
  }
 
  cnt = 0;
  while (1) {
    sa_len = sizeof(new_sa);
    if ((comm_sock = accept(listen_sock, (struct sockaddr *)&new_sa, &sa_len)) < 0) {
      fprintf(stderr, "accept() failure\n");
      exit(1);
    }
    ++cnt;
 
    args = (struct ThreadArgs *)malloc(sizeof(struct ThreadArgs));
 
    args->sock = comm_sock;
    args->cnt  = cnt;
    args->sa   = new_sa;
 
    ta[ta_count++] = args;

    if (pthread_create(&thread_id, NULL, (void *)thread, (void *)args) != 0) {
      fprintf(stderr, "pthread_create() failure\n");
      exit(1);
    }
  }
  return 0;
}
 
void *thread(void *arg)
{
  int sock, cnt, n, msg_len;
  struct sockaddr_in sa;
  char buf[BUFSIZE];
 
  if (pthread_detach(pthread_self()) != 0) {
    fprintf(stderr, "pthread_detach() failure\n");
    exit(1);
  }
 
  struct ThreadArgs *args = arg;
  sock = args->sock;
  cnt  = args->cnt;
  sa   = args->sa;
 
  printf("Client %d (%s) connected\n", cnt, inet_ntoa(sa.sin_addr));
 
  while (1) {
    if ((n = recv(sock, buf, sizeof(buf), 0)) > 0) {
      int i, sock2;
      char buf2[BUFSIZE + 20];
      msg_len = sprintf(buf2, "Client %d: %.*s\n", cnt, n, buf);
      printf("%s", buf2);
      for (i = 0; i < ta_count; i++) {
        if (send(ta[i]->sock, buf2, msg_len, 0) != msg_len) {
          fprintf(stderr, "send() failure\n");
          exit(1);
        }
      }
    }
  }
  close(sock);
 
  printf("Client %d disconnecter\n", cnt);
  printf("\n");
 
  free(arg);
 
  return;
}

コード:

/*
  クライアントプログラム
  $ gcc -o echo_client echo_client.c
  $ ./echo_client 127.0.0.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <pthread.h>
 
#define MSGSIZE 512
#define BUFSIZE 1024
 
void *thread(void *arg);

int main(int argc, char *argv[])
{
  int sock, msg_len;
  struct sockaddr_in sa;
  char *server_ip;
  char msg[MSGSIZE];
  pthread_t thread_id;
 
  if (argc != 2) {
    fprintf(stderr, "usage: echo_client SERVER_IP_ADDRESS\n");
    exit(1);
  }
  server_ip = argv[1];
 
  sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 
  memset(&sa, 0, sizeof(sa));
  sa.sin_family = AF_INET;
  sa.sin_port = htons(49152);
  sa.sin_addr.s_addr = inet_addr(server_ip);
 
  if (connect(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
    fprintf(stderr, "connect() failure\n");
    exit(1);
  }
 
  if (pthread_create(&thread_id, NULL, (void *)thread, (void *)sock) != 0) {
    fprintf(stderr, "pthread_create() failure\n");
    exit(1);
  }

  while (1) {
    printf("please input a message!\n");
    printf("> ");
    scanf("%s", msg);
    msg_len = strlen(msg);
 
    if (send(sock, msg, msg_len, 0) != msg_len) {
      fprintf(stderr, "send() failure\n");
      exit(1);
    }
 
    if (strcmp(msg, "exit") == 0) {
      exit(1);
    }
  }
  return 0;
}

void *thread(void *arg)
{
  char buf[BUFSIZE];
  int n;
  int sock = (int)arg;

  while (1) {
    if ((n = recv(sock, buf, sizeof(buf), 0)) > 0) {
      buf[n] = '\0';
      printf("Echo message: ");
      printf("%s\n", buf);
    } else if (n < 0) {
      fprintf(stderr, "recv() failure\n");
      exit(1);
    }
    //printf("\n");
    //close(sock);
  }
  return 0;
}


Re: ネットワークプログラミングについて

Posted: 2012年8月02日(木) 06:31
by Rance
クライアント側でもスレッドを利用すればいいんですね!

若干の不具合(文字列の表示等)はありましたが、動作自体は問題ありませんでした。
とても、感謝しております!
ありがとうございました!