質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.47%

  • Linux

    4521questions

    Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

C言語 Linuxを使ってtcpのチャットシステムの応用?

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,300

monamona154

score 7

C言語でサーバとプログラム間でのプログラムを作成したいのです。 
サーバを起動してクライアントが1~9の数字をどれかの数字を送信する→サーバが数字を受け取る→その送られた数字の段の九九をクライアントに送信して表示 というのを1つのサーバと2つ以上のクライアントを使用して作成したいです。 
Linuxで端末を複数起動してやりたいです。
tcpでチャットが出来るプログラムが以下になります。
これを修正して九九が出るように修正してもらいたいです。
人任せで申し訳ないし自分のためにならないとも思うのですが、課題のため修正したプログラムを見せてもらいたいです。
回答お願いします。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define PORT 20007
#define BUF_SIZE 0x1000

 static void server(int port){
    struct sockaddr_in sin;
    fd_set rfds;
    int ld, sd[5], len, max,x,y;
    char *buf, str[256];

    if ((buf = malloc(BUF_SIZE)) == NULL) {
    perror("malloc");
    return;
    }

for(x=0;x<5;x++) sd[x] =  -1;

    if ((ld = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
    perror("socket");
    goto close_and_end;
    }

    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);
    if (bind(ld, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
    perror("bind");
    goto close_and_end;
    }
    if (listen(ld, 3) < 0) {
    perror("listen");
    goto close_and_end;
    }

 loop:
    FD_ZERO(&rfds);
    FD_SET(ld, &rfds);
    max = ld;

for(x=0;x<5;x++){
    if (sd[x] >= 0) {
    FD_SET(sd[x], &rfds);
    if (max < sd[x]) max = sd[x];
    }
 }

    select(max + 1, &rfds, NULL, NULL, NULL);

for(x=0;x<5;x++){
    if (sd[x] > 0 && FD_ISSET(sd[x], &rfds)) {
    if ((len = read(sd[x], buf, BUF_SIZE)) > 0) {
        if (write(sd[x], buf, len) < 0) {
        close(sd[x]);
        sd[x] = -1;
        }
for(y=0;y<5;y++){
  if(x!=y){
        if (sd[y] > 0) {
        if (write(sd[y], buf, len) < 0) {
            close(sd[y]);
            sd[y] = -1;
        }
        }
  }
 }
    }
     else {
        if (len < 0) perror("read");
        close(sd[x]);
        sd[x] = -1;
    }
    }
 }

    if (FD_ISSET(ld, &rfds)) {
    int tmpd;

    len = sizeof(sin);
    if ((tmpd = accept(ld, (struct sockaddr*)&sin,   (socklen_t*)&len))
        < 0) {
        perror("accept");
        goto close_and_end;
    }
    inet_ntop(AF_INET, &sin.sin_addr.s_addr, str, sizeof (str));
    printf("connected from %s\n", str);

    if(sd[0]<0)
      sd[0]=tmpd;
    else if(sd[1]<0)
      sd[1]=tmpd;
    else if(sd[2]<0) 
      sd[2]=tmpd;
    else if(sd[3]<0) 
      sd[3]=tmpd;
    else if(sd[4]<0) 
      sd[4]=tmpd;
    else if(sd[5]<0) 
      sd[5]=tmpd;
    else{
      strcpy(buf, "Server too busy\n");
      send(tmpd, buf, strlen(buf), 0);
      close(tmpd);
    }
    }
    goto loop;

 close_and_end:
    for(x=0;x<5;x++){
    if (sd[x] >= 0) close(sd[x]);
    if (ld >= 0) close(ld);
    }

    free(buf);
}

 static void client(unsigned int ip, int port){
    struct sockaddr_in sin;
    char *buf;
    int sd, len, i;
    fd_set rfds;
    int max;

    if ((buf = malloc(BUF_SIZE)) == NULL) {
    perror("malloc");
    return;
    }

    if ((sd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
    perror("socket");
    goto close_and_end;
    }
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);
    sin.sin_addr.s_addr = htonl(ip);
    if (connect(sd, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
    perror("connect");
    goto close_and_end;
    }

loop:
    FD_ZERO(&rfds);
    max=1;

    if (0 < sd){
      FD_SET(sd, &rfds);
      if(max<sd) max = sd;
    }

    FD_SET(0, &rfds);

    select(max + 1, &rfds, NULL, NULL, NULL);

    if(FD_ISSET(0, &rfds)){
        if (fgets(buf, BUF_SIZE, stdin) <= 0)
        goto close_and_end;
        len = strlen(buf);
        if (send(sd, buf, len, 0) < 0) {
        perror("send");
        goto close_and_end;
        }
    }

    if(FD_ISSET(sd, &rfds)){
        len = recv(sd, buf, BUF_SIZE, 0);
        if (len <= 0) {
        if (len < 0) perror("send");
        goto close_and_end;
        }
        for (i = 0; i < len; i++) putchar(buf[i]);
    }
    goto loop;

 close_and_end:
    if (sd >= STDIN_FILENO) close(sd);
    if (sd >= 0) close(sd);
    free(buf);
}

 static void usage(void){
    printf("server mode: tcp2 -s\n");
    printf("client mode: tcp2 -c\n");
    exit(0);
}

 int main(int argc, char **argv, char **env){
    if (argc != 2) usage();
    if (argv[1][0] != '-') usage();
    switch (argv[1][1]) {
    case 's':
    server(PORT);
    break;
    case 'c':
    {
    struct hostent *ent;

    ent = gethostbyname("localhost");
    client(ntohl(*(int*)ent->h_addr_list[0]), PORT);
    break;
    }
    default:
    usage();
    }

    exit(0);
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    2016/07/03 08:50

    こちらの質問が他のユーザから「やってほしいことだけを記載した丸投げの質問」という指摘を受けました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 1

0

localhost って書いてあるんで端末二台では動かないと思いますよ。
動作テストしましたか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/07/03 01:01

    ローカルホストです。
    一つのパソコンで端末を開いて行うつもりです。
    パソコン初心者なもので、そこらへんの説明が下手ですいません

    キャンセル

  • 2016/07/03 02:03

    端末…ああ確かに。
    失礼しました。
    それで、ちゃんと動きましたか?

    キャンセル

  • 2016/07/03 12:24

    動作は確認できました

    キャンセル

  • 2016/07/03 12:28

    どのように起動してどのように操作してどのような出力が得られましたか?

    キャンセル

  • 2016/07/03 12:33

    端末ひとつでサーバが起動されて クライアント2つも起動してチャットが打てるようになりました。自分がチャットを打った端末では打った文字が2回出てきて他は1回だけです。
    サーバの端末はクライアントが接続されたら「接続されました」のような文章が表示されています

    キャンセル

  • 2016/07/03 12:36 編集

    コマンドラインオプションはどうしました?
    「接続されました」というメッセージはソース中にありませんが、どうしてそれが出ていますか?
    他にもメッセージが出ているはずですが、それはどのようなものですか?

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Linux

    4521questions

    Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。