• ベストアンサー

Cにおける通信プログラミングの問題のコトですが。

いま、Cでかかれた受信側と送信側のプログラムがあります。(送信側はメッセージ(文字列)を送って終了。受信側はその文字列を受け取って、それを表示して終了する、といった簡単なモノです。)(ソケットを使ったモノです。)(コネクションレスです。)  このプログラムを改造して、受信側で送信者のIPアドレスとホスト名を表示するようにしなさ~い♪ という課題がだされたのですが、 Cでは、そういう関数が用意されているのでしょうか? もしあるとしたら、その関数の使い方など教えてください。 また、メンドウだったら使い方が載っているページなど教えてください。

noname#4530
noname#4530

質問者が選んだベストアンサー

  • ベストアンサー
  • Fooky
  • ベストアンサー率71% (59/82)
回答No.2

(UNIX系OSでの作成を仮定しています) ipのmanページも見ておいた方がいいと思います。 % man ip recvfrom()のmanページでは、recvfrom()の 引数は、 recvfrom(int s, void *buf, size_t len, int flags,      struct sockaddr *from, socklen_t *fromlen); となっていて、fromに発信元アドレスが入る、という形だと 思います。しかし、sockaddr構造体はネットワークプロトコル ごとに使い分けます。(実際はインターネットプロトコルしか 使ったこと無いですが) で、インターネットプロトコル用のsockaddr構造体 であるsockaddr_in構造体に関する記述が、 ipのmanページに書いてあります。 (ただしこれはLinuxの場合。手元のSunOSでは man 4f inetに、IRIXではman 7 inetに 記載されていました。) recvfrom()のコールの仕方としては、 struct sockaddr_in from; socklen_t fromlen = sizeof(from); recvfrom(s, buf, len, 0, (struct sockaddr *)&from, fromlen); の様に、sockaddr_in構造体へのポインタをsockaddr構造体への ポインタにキャストしたものを引数に指定します。 fromに入った接続元ホストのデータをホスト名へ変換するには、 hostent *hstent; hstent = gethostbyaddr((char *)&from.sin_addr, sizeof(from.sin_addr), AF_INET); とすることで、hstent->h_nameの中に ホスト名が文字列として入ります。

noname#4530
質問者

お礼

ありがとうございました。 ところで、今お礼を書くにあたって再度Fookyさんの回答を読んでいて、 驚き、そしてヘナヘナとうなだれてしまいました。 >socklen_t fromlen = sizeof(from); これですっ!これをずっと忘れていてうまくいかなかったんです! 本当に驚きましたよ。Webページを5つほど渡り歩いてやっと気付いたのに。 まさに灯台の下をもう一度見るべきでした。 はじめ、socklen_tというのをみて、なんかまたワケワカランのが、、、 と思って、カル~ク流していたのではないかと思われますが、 まさかそこがソコとワ、、、 なんにしろ、ありがとうございました。そして、お礼がおくれてすみませんでした。

その他の回答 (1)

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.1

文字列の受信は recvfrom() を使っているのですね? 5番目の引数は何ですか? こいつから、送信者の IP アドレスが取得できますね。 IP アドレスからホスト名を引き出すには gethostbyaddr() という関数を 使います。 > 関数の使い方など教えてください 多分、unix 上での作成だと思うのですが、一番手軽で確実なのはオンライン マニュアル(man コマンド)です。例えば、さっきの関数の使い方を調べるには % man gethostbyaddr と、やります( % はプロンプトのつもりだから、入力しちゃ駄目ですよ)。

noname#4530
質問者

お礼

ありがとうございました! そうです。recvfrom()を使っていたのです。 相手のアドレスが5番目の引数の構造体に入るんでしたか。 しかし、どうもオカシイ。オカシイゾ~~~。 その構造体のメンバを参照しても、%sではnull、%dでは0。 なんでなんだ~~~と苦悩してカタッパシからWebページを読んでいったら、 最後の引数を&lenとすると、recvfromの前に、len = sizeof(構造体)がないと ダメだったんですね。これに気付くのにどれだけかかったことか、、、 それでずっと悩んでいてお礼が遅れてしまったことをお詫びしておきます。ごめんなさい。

関連するQ&A

  • RS232C通信について

    PC-マイコン間の通信において マイコンから信号を受信するために ReadFile関数の第3引数を受信文字バイト数にしたところ, PC側のプログラムでReadFile関数を実行するごとに 受信文字が1バイトずつ右にずれるような受信をし始めました. 1ループ→"abcd" 2ループ→"dabc" 3ループ→"cdab" こちら側の意図としては ReadFile関数を一度実行すると, ReadFile関数の第2引数に上書きされるものだと思っていたのですが, 具体的にはどのように文字が格納されていくのでしょうか? また,あわせてWriteFile関数で文字列をマイコンに送信しているのですが, 上述の文字列と合体した状態で受信してしまいます. 具体的には char c[17]="abcdefghijklmnop"; char p[13]="100100100100"; ハンドルの指定 ループ始め ・・・ ReadFile (hCom, c, strlen(c), &dwRead, NULL); WriteFile (hCom, p, strlen(p), &wbyte, NULL); ・・・ ループ終わり ハンドルクローズ と記述しています. 仮にマイコン側から"abcdefghijklmnop"が送られてきた場合 cには 1ループ→"100100100100abcd" 2ループ→"100100100100pabc" です. どこに課題があるでしょうか よろしくお願いします.

  • ソケットプログラミングに関する質問です

    ソケットプログラミングに関する質問です 最近ソケットプログラムに興味があり、勉強をしているのですが、 手始めにと下記の2つのプログラムをそのまま記述し http://cs.baylor.edu/~donahoo/practical/CSockets/code/TCPEchoClient.c http://cs.baylor.edu/~donahoo/practical/CSockets/code/TCPEchoServer.c TCPEchoClientプログラムから送信した英数字をTCPEchoServerがキャッチして TCPEchoClientの方へ送り返すプログラムを作ってみました。 その後、応用として手始めにTCPEchoClient側の送信元IPアドレスと送信した文字列 ex: 192.xxx.xxx.xx 'Hello World!' を送り返すプログラムを作成するために、 同じサイト内にあったHandleTCPClientを下記の通り 改造してみたのですが、引数に問題があるとエラーが出て先へ進めません。>< #include<stdio.h> #include<sys/socket.h> #include<unistd.h> #define RCVBUFSIZE 256 /* 受信バッファのサイズ */ void DieWithError(char *errorMessage); /* エラー処理関数 */ void HandleTCPClient(int clntSocket, int echoClntAddr) /* TCPクライアント関数処理 */ { char echoBuffer[RCVBUFSIZE]; /* エコー文字列のバッファ */ int recvMsgSize; /* 受信メッセージのサイズ */ struct clintIP echoClntAddr; /* クライアントのIPを取得 */ /* クライアントからの受信メッセージ */ if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE,clintIP,0)) < 0) DieWithError("recv() failed"); /* 受信した文字列を送信し、転送が終了していなければ次を受信する */ while (recvMsgSize > 0) /* 0は転送の終了を意味する */ { /* メッセージをクライアントにエコーバックする */ if (send(clntSocket,echoBuffer,recvMsgSize, 0) != recvMsgSize) DieWithError("send() failed"); /* 受信するデータが残っていないか確認する。 */ if ((recvMsgSize = recv(clntSocket, echoBuffer,RCVBUFSIZE, 0)) < 0) DieWithError("recv() failed"); } close(clntSocket); /* クライアントソケットをクローズする */ } 単純にTCPEchoServerの echoClntAddr.sin_addrという箇所が送信元のIPを 引っ張ってきてるからHandleTCPClientの方へ 関数をstructで引っ張ってくればいいと思ったのですが、そういうわけでもないのです。

  • socketプログラミングについて

    C++でsocketの練習のためにソケットを開き、文字列の送信を行うだけのサーバクライアントプログラムを作成したのですが、どうも上手く動作してくれません。 クライアント→サーバへ文字列を送信する前に、 1.サーバがソケットを開き、9999ポートでアクセスを待つ 2.クライアントがソケットを作成し、サーバの9999ポートにアクセスする 3.クライアントが文字列をサーバへ送信し、サーバが文字列を表示 ということをしたいのですが、2の部分でつまずいています。 プログラムをネットワークに接続されているコンピュータ上で実行すると動作するのですが、(client 192.168.15.17 9999)単独でサーバ・クライアントを起動させ、localhost当てに接続(client localhost 9999)しようとしても「No route to host」と表示されて、接続すら出来ません。 ためしにサーバを起動させている状態で「telnet localhost 9999」とするとどうやらサーバに接続されているようです。 localhostでやる場合は特別なソケット操作が必要になるのでしょうか?

  • シリアル通信のデータ受信について質問です

    PCからマイコン(H8/3664)に文字を送信したいのですが、受信のしかたがわかりません。PC側のプログラムはC#を使っていて、8bit送信しています。マイコン側はC言語で、8bitで送られた文字を、C言語でどういう風に受信したらいいかわかりません。受信する関数があるのでしょうか?ちなみに割り込みは使いません。

  • C#でソケット通信

    初歩的な質問ですみません。 クラアント側とサーバー側にそれぞれC#で作ったプログラムをインストールし、 クライアントからサーバーにデータを繰り返し送信したいとき、 そのプログラム内でソケット接続して送ることはできるでしょうか? できるとして、どのような手順でソケット接続し、データを送ればいいのでしょうか? まったくの初心者です。 よろしくお願いします。

  • プログラミングC

    以下に示すプログラムは、キーボードから39文字以下の文字列を入力した後で、その文字列を表示するプログラムである。ただし、文字列の表示においては、printf命令における変換指定で、%sを使用するのが一般的であるが、以下のプログラムあえて%sを使用せずに、%cを使っている。このプログラムについてキーボードから入力される文字列の文字数が391文字以下である限り、その文字列を正しく表示できるよう、下線部を埋めてプログラムを完成させなさい。 char x[40],i printf("39文字以下の文字列を入力:"); scanf("%s",x); for(i=0;x[i]_____;i++) printf("%c",x[i]); printf("です。\n"); [実行例] 39文字以下の文字列を入力:programming 入力された文字列はprogrammingです。

  • ソケットプログラミングについて

    こんにちは。 前回、質問しました「バード」という者です。 ソケットプログラミングについて質問します。 PC1から、jpegやmpegファイルを送信しPC2で受信するというプログラムをC言語で作ってみたいと思っています。 以前、少しだけJAVAプログラミングでPC1(送信側)からPC2(受信側)へデータを送信するプログラムを作ったのですが、作ったプログラムの概要を以下に示します。 [送信側] (ファイルオープン) InputStream in = new FileInputStream(ss); BufferedInputStream bin = new BufferedInputStream(in); ↓ (データを読みsendメソッドにて随時送信) while((c = bin.read(buffer, 0, buffer.length))!=-1){ dPacket = new DatagramPacket(buffer,buffer.length,iAddress,port); dSocket.send(dPacket); } ↓ (ファイルとソケットクローズ) dSocket.close(); [受信側] (ファイルオープン) OutputStream out = new FileOutputStream(args[1]); BufferedOutputStream bout = new BufferedOutputStream(out); ↓ (送信側から来たデータをreceiveメソッドにて受信) while(true){ dPacket = new DatagramPacket(buffer,buffer.length); dSocket.receive(dPacket); } ↓ (ファイルとソケットクローズ) dSocket.close(); 上記に示す様に、ファイルをオープンし、DatagramSocketとDatagramPacketクラスを用いて送受信し最後に、ファイルをクローズするという形式をとっていました。 C言語の場合でも、ファイルオープン→send関数,receive関数等を用いて送信・受信→ファイルクローズという形をとる事ができるのでしょうか?FTPプログラムやエコープログラムを、よく見かけるのですが・・・・

  • プログラミング(C言語)について

    プログラミングの課題です。いろいろ考えたのですがうまくいきません。 文字検索プログラムをC言語で作ろうとしています。多くの文字列(例:ABAABCBBABC・・・)の中から検索したい文字列(例えばABC)を入力して、その文字列が何か所に含まれてそれぞれ何文字目に始まるかを求めるようにするというものです。 どなたかわかる方がいらっしゃいましたらご回答よろしくお願いいたします。できれば詳しく式などを書いていただきたいです。

  • c# ソケット非同期通信プログラム

    C#でソケット非同期通信プログラムを作りたいと思い勉強しております。ちなみにソケット通信はc言語ではやっておりました。 今作りたいと思ってるプログラム ・ラジオボタンで接続形態(サーバー・クライアント)を選択。 ・送信ボタンを押した時は送信 ・受信した時は受信データをテキストボックスに表示 ・コネクション数は1つで送受信を行う お手数ではございますが、参考になる様なサイトやアドバイス等があれば宜しくお願い致します。

  • PIC-PCシリアル通信プログラム

    PICとPCでRS232のシリアル通信を行おうとしているんですけれど、 PICからPCに文字列を送ろうと たとえば PIC側からプログラムで puts("A\0");とデータを送信して ReadFile()関数でPC側で受信しているんですけれど、 受信したデータを画面表示されると Aフフフフフフフフフフフフフフフフフフフフフフフフと表示されてしまいます。 ちなみに送信データをNULLだけにしても フフフフフフフフフフフフフフフフフフフフフフフフフを表示されます。 これを解決する方法がわかりません。 どなたか教えてください。

専門家に質問してみよう