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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C

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

UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

Q&A

解決済

2回答

679閲覧

UDP通信とC言語の線形連結リストについて

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

0グッド

0クリップ

投稿2023/01/26 20:16

前提

C言語でUDP通信を使ったチャットプログラムを製作中、クライアント側からのチャット参加要求の処理に困っています。

実現したいこと

ここに実現したいことを箇条書きで書いてください。

  • 線形連結リストを使って、クライアント用のクライアント管理データを作成し、データ集合内に保持する。(可能であれば削除まで)

該当のソースコード

C

1 2//サーバー側のプログラム 3 4#include <stdio.h> 5#include <string.h> 6#include <arpa/inet.h> 7#include <stdlib.h> 8#include <unistd.h> 9#include <time.h> 10 11#include "MessagePacket.h" 12 13// 静的グローバル変数 14static int g_sock; // チャットクライアントと通信するために利用するソケット 15 16// 構造体の宣言 17struct ClientData { 18 char srcAddr[INET_ADDRSTRLEN]; // クライアントのアドレス 19 u_short srcPort; // クライアントのポート番号 20 char participantName[MSG_BUF_SIZE]; // 参加者名 21 time_t lastReceivingTime; // メッセージを最後に受信した時刻 22}; 23 24struct Node { 25// struct ClientData client; 26// struct Node* next; 27//}; 28 29// 静的グローバル変数 30static struct Node* g_root; 31 32void SvrInitialize( 33 int sock) // [IN] チャットクライアントと通信するためのソケット 34{ 35 // チャットクライアントと通信するためのソケットをこのファイル内で保持する. 36 g_sock = sock; 37 38int SvrJoinRequestHandler( 39 struct sockaddr_in clntAddr, // [IN ] クライアントのアドレス構造体 40 char* msgBuf, // [IN ] メッセージバッファ 41 short msgLen) // [IN ] メッセージの長さ 42{ 43 int result = 1; // 戻り値 44 45 // 送信元のIPアドレスとポート番号を取得する. 46 char srcAddr[INET_ADDRSTRLEN]; 47 inet_ntop(AF_INET, &clntAddr.sin_addr.s_addr, srcAddr, INET_ADDRSTRLEN); 48 u_short srcPort = ntohs(clntAddr.sin_port); 49 50 // クライアントの参加者名として受信した文字列を終端し,表示する. 51 msgBuf[msgLen] = '\0'; 52 printf("クライアント(IPアドレス:%s, ポート番号:%d)からの参加要求:%s\n", srcAddr, srcPort, msgBuf); 53 54 // クライアントからの参加要求を処理する. 55 // ※参加要求を送ってきたクライアント用のクライアント管理データを作成し, 56 // データ集合内に保持する必要がある. 57 //未実装 58 59 // グループへの参加応答を送信する. 60 short sentByte = SendMessagePacket( 61 g_sock, // クライアントとの通信用ソケット 62 clntAddr, // クライアントのアドレス (参加要求送信元のアドレス) 63 MSG_JOIN_RESPONSE, // グループへの参加応答のメッセージID 64 msgBuf, // クライアントの参加者名 65 msgLen // クライアントの参加者名の長さ 66 ); 67 if (sentByte < 0) { 68 fprintf(stderr, "error: SvrJoinRequestHandler() -> SendMessagePacket(): %d\n", sentByte); 69 } 70 // 送信バイト数(エラーの場合を含む)を戻り値として返す. 71 result = sentByte; 72 return result; 73}

試したこと

ノード構造体の記述までは行うことができました(コード13~27)が、そもそも線形連結リストに慣れていないもので、UDP通信においてのリストの生成や追加については徹夜で調べても分かりませんでした。ヒントでもいいので現状打破のきっかけが欲しいです。

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

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

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

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

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

jimbe

2023/01/27 01:48 編集

リスト(の課題)が分からないという質問は teratail に度々あります。 回答も付いていますので、参考にしては如何でしょうか。
guest

回答2

0

ヒントでもいい

とのことなので、漠然とした内容ですがコメントではなく回答欄で。

UDPの通信相手を管理するのにリスト構造を使うことでなんら特殊な事情は発生しないと思います。

UDPとリスト構造の話は全く別です。それらを(勝手に)結びつけてしまって、そういう(多分存在しない)サンプルを探すことで手詰まりに陥っているのではないかと想像します。

そんなサンプルは(多分)ないので探すのはやめましょう。

リスト構造について、'C言語 リスト構造' あたりをキーに検索すればたくさんの情報が得られると思います。それらをいくつか読んで(コピペを期待するのではなく)内容を理解します。
そうした後、あなたが保存したいUDPに関する情報(これは選別出来ているようです)を保持するプログラムを「作り上げれば」よいのではないかと思いますがいかがでしょう。

投稿2023/01/26 22:28

thkana

総合スコア7610

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

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

0

ベストアンサー

UDP はともかく任意のデータを保持するようなリング状双方向リストならこんな感じ。
UDPと関係無いことを表す意味でもリスト部分は別ファイルで、ノードのポインタ操作が main に出てこないようにしてみました。

c

1#include <stdio.h> 2#include <string.h> 3 4#include "listlib.h" 5 6typedef struct { //リストに保存するデータ(ダミー) 7 char name[32]; 8 int value; 9} CLIENT_DATA; 10 11void print_clients(LIST list) { 12 for(CLIENT_DATA *client = next_node(list); client != NULL; client = next_node(NULL)) { 13 printf("name=%s, value=%d\n", client->name, client->value); 14 } 15} 16 17void add_client(LIST list, char *name, int value) { 18 CLIENT_DATA *client = add_node(list, sizeof(CLIENT_DATA)); 19 strcpy(client->name, name); 20 client->value = value; 21} 22 23void remove_client(LIST list, char *name) { 24 for(CLIENT_DATA *client = next_node(list); client != NULL; client = next_node(NULL)) { 25 if(strcmp(client->name, name) == 0) { 26 remove_node(client); 27 break; 28 } 29 } 30} 31 32int main(int argc, char **argv) { 33 printf("initial ----\n"); 34 LIST list = alloc_list(); 35 print_clients(list); 36 37 printf("add AAA ----\n"); 38 add_client(list, "AAA", 1); 39 print_clients(list); 40 41 printf("add BBB ----\n"); 42 add_client(list, "BBB", 2); 43 print_clients(list); 44 45 printf("add CCC ----\n"); 46 add_client(list, "CCC", 3); 47 print_clients(list); 48 49 printf("remove BBB ----\n"); 50 remove_client(list, "BBB"); 51 print_clients(list); 52 53 printf("remove AAA ----\n"); 54 remove_client(list, "AAA"); 55 print_clients(list); 56 57 printf("add DDD ----\n"); 58 add_client(list, "DDD", 4); 59 print_clients(list); 60 61 printf("remove DDD ----\n"); 62 remove_client(list, "DDD"); 63 print_clients(list); 64 65 printf("free ----\n"); 66 free_list(list); 67 68 return 0; 69}

listlib.h

c

1#ifndef LISTLIB_H_ 2#define LISTLIB_H_ 3 4typedef struct list_node { 5 struct list_node *next; 6 struct list_node *prev; 7 int value[0]; 8} LIST_NODE; 9 10typedef struct list_node* LIST; 11 12LIST alloc_list(); 13void *add_node(LIST list, size_t size); 14void *next_node(LIST list); 15void remove_node(void *value); 16void free_list(LIST list); 17 18#endif /* LISTLIB_H_ */

listlib.c

c

1#include <stdio.h> 2#include <stdlib.h> 3 4#include "listlib.h" 5 6LIST alloc_list() { 7 LIST_NODE *head = malloc(sizeof(LIST_NODE)); 8 head->next = head; 9 head->prev = head; 10 return head; 11} 12 13void *add_node(LIST list, size_t size) { 14 if(list == NULL || size < 0) return NULL; 15 LIST_NODE *node = malloc(sizeof(LIST_NODE) + size); 16 node->next = list; 17 node->prev = list->prev; 18 node->prev->next = node; 19 node->next->prev = node; 20 return node->value; 21} 22 23void *next_node(LIST list) { //strtok 的 24 static LIST_NODE *list_head = NULL, *current_node = NULL; 25 26 if(list == NULL) { 27 if(current_node == NULL) return NULL; 28 current_node = current_node->next; 29 } else { 30 list_head = list; 31 current_node = list->next; 32 } 33 if(current_node == list_head) { 34 current_node = NULL; 35 return NULL; 36 } 37 return current_node->value; 38} 39 40void remove_node(void *value) { 41 if(value == NULL) return; 42 LIST_NODE *node = value - sizeof(LIST_NODE); 43 node->next->prev = node->prev; 44 node->prev->next = node->next; 45 free(node); 46} 47 48void free_list(LIST list) { 49 if(list == NULL) return; 50 for(LIST_NODE *node = list->next; node != list; ) { 51 node = node->next; 52 free(node->prev); 53 } 54 free(list); 55}

実行結果

initial ---- add AAA ---- name=AAA, value=1 add BBB ---- name=AAA, value=1 name=BBB, value=2 add CCC ---- name=AAA, value=1 name=BBB, value=2 name=CCC, value=3 remove BBB ---- name=AAA, value=1 name=CCC, value=3 remove AAA ---- name=CCC, value=3 add DDD ---- name=CCC, value=3 name=DDD, value=4 remove DDD ---- name=CCC, value=3 free ----

投稿2023/01/29 08:47

編集2023/01/30 10:57
jimbe

総合スコア12545

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問