🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

13320閲覧

C++における複数ClientのTCP Socket通信の実装について

Nemux

総合スコア6

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/09/27 15:47

編集2019/09/27 15:51

前提・実現したいこと

C++で下記の図のように同一LAN内にServerと複数台のClientを作り、TCPのSocketで通信したいと思っています。
双方で文字列を送受信できるようにしたいです。
送受信するデータは下記のように、それぞれのClientに割り振ったIDと内容、時間をまとめてJSONを作り、それをString形式で送ります。

json

1{ 2 'id': 1, 3 'content': 'abcd', 4 'time': 'HH:mm:ss' 5}

![setumei

発生している問題

検索エンジンで調べてみてもC++のSocket通信の記事自体少ないのに複数Clientに関する記事が全く見つからないのでServer、Clientのコードが書けない。

補足情報(FW/ツールのバージョンなど)

VS C++ 2019
Windows10 Pro

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

Windows環境から利用するネイティブAPIは「WinSock」です。このWinSockはC言語用のAPIになっていますが、C++プログラムからそのまま呼び出し可能です。入門向けに「winsockプログラミング:Geekなぺーじ」をオススメしておきます。


C++ネイティブなネットワークライブラリとしては、Boost.ASIO などが有名です。内部的にはWinSockが利用されますが、モダンなC++ライブラリ設計になっています。(代償として、その設計思想を理解しないと使いこなすのは非常に難しいです。)

投稿2019/09/27 16:43

yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

すみませんが問題となっている箇所がよくわからないのですが、TCPのプログラムを検索してみるとhttp://research.nii.ac.jp/~ichiro/syspro98/server.html の様な物が現れました
ただこれではClient 1台にしか対応していないですね
複数クライアントに対応するには、クライアントの応答を待つAccept用スレッドと一つとClientの相手をする通信スレッドが対応クライアントの数だけ必要となります。
サーバー側ではAcceptから抜けた時がてクライアントと接続した事を意味し、この時新しいソケット番号がAcceptから返ってくるはずです。別のスレッドにこのソケット番号を渡してそちらでクライアントとのTCP通信を行う様にイベントを投げて、また次のクライアントからのAcceptを待つようなループを作る必要があります。

投稿2019/09/27 16:25

takahirot

総合スコア16

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Nemux

2019/09/27 16:35

回答ありがとうございます。 まず問題の箇所は参考資料がなく、Server及びClientのソースが書けないということです。 そこで、具体的にはどのように変更すればよいかよろしいでしょうか?ご教授いただければ幸いです。
takahirot

2019/09/28 03:50

5年以上前に何かで使ったサンプルです。 TCPサーバー側 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <sys/types.h> #ifdef _WIN32 #include <winsock.h> #else #include <sys/socket.h> #include <arpa/inet.h> #endif void childproc(int fd); int main(int argc, char **argv) { int listenfd, connfd; pid_t childpid; int clilen; struct sockaddr_in cliaddr, servaddr; if (argc != 2) { perror("Usage: cserver <Port>\n"); exit(0); } listenfd = socket(AF_INET, SOCK_STREAM, 0); memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(atoi(argv[1])); bind(listenfd, (const struct sockaddr *) &servaddr, sizeof(servaddr)); listen(listenfd, 5); for (;;) { clilen = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen); childproc(connfd); close(connfd); } } #define OUT_BUFFER_SIZE 1024 void childproc(int fd) { char buf[OUT_BUFFER_SIZE] = {0}; while (recv(fd, buf, 2, 0) > 0) { /* The first 16 bit is the length of payload. */ unsigned short * p = (unsigned short *)buf; int len = (*p) & 0xff; printf("Got a new packet with len %d.\n", len); if (recv(fd, buf + 2, len + 2, 0) == len + 2) { /* Read the other 2 bytes in head and payload. */ int i; unsigned long * head_p = (unsigned long *)buf; unsigned long head = * head_p; printf("head.len = %u\n", (unsigned int)(head & 0xff)); printf("head.id = %u\n", (unsigned int)((head >> 16) & 0x3f)); printf("head.type = %u\n", (unsigned int)((head >> 22) & 0x3)); printf("payload:\n"); for (i = 0; i < len; i++) { printf("0x%x\t", buf[4 + i]); if ((i % 8) == 7) { printf("\n"); } } printf("\n"); send(fd, buf, len + 4, 0); /* Send the packet back to com-module, for test purpose. */ } } }
takahirot

2019/09/28 03:51

TCP クライアント #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> int main(int argc, char **argv) { int sockfd; int ret; struct sockaddr_in servaddr; char buf[80]; const char *msg = "This is a test string\0"; if (argc != 3) { perror("Usage: cclient <IPaddress> <Port>\n"); exit(0); } sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == 1) { perror("Error sockte\n"); } bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; inet_pton(AF_INET, argv[1], &servaddr.sin_addr); servaddr.sin_port = htons(atoi(argv[2])); connect(sockfd, (const struct sockaddr *) &servaddr, sizeof(servaddr)); ret = send(sockfd, msg, 15, 0); fprintf(stderr, "Sent %d bytes\n", ret); ret = recv(sockfd, buf, 80, 0); buf[79] = '\0'; fprintf(stderr, "Received back %d bytes\n", ret); fprintf(stderr, "Received %s\n", buf); exit(0); }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問