アプリ版:「スタンプのみでお礼する」機能のリリースについて

ソケットプログラミングに関する質問です
最近ソケットプログラムに興味があり、勉強をしているのですが、

手始めにと下記の2つのプログラムをそのまま記述し

http://cs.baylor.edu/~donahoo/practical/CSockets …
http://cs.baylor.edu/~donahoo/practical/CSockets …
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で引っ張ってくればいいと思ったのですが、そういうわけでもないのです。

A 回答 (2件)

ありもののクラスやライブラリを使う前に一度APIを叩くことを地道に実験されたほうが利益になるかと。

ソケットの場合は特に。
以下に入門になかなか良いあきみちさんのサイトを載せておきます。もし開発環境がWindowsでない場合でもページ内にLinux用のものがあり有用です。
http://www.geekpage.jp/programming/winsock/

そしてもうすこし突っ込んだことを勉強してソケットオプションや、ソケット通信の仕様などを知るには以下のサイトが有名です。サンプルもシンプルに作られていて参考になりますが、残念ながらマルチスレッドとの併用などがあまり詳しく書かれていないのでご自分で実験されてみるとよろしいかと。このサイトはWinsockがメインで説明されていますがLinuxなどと共通している内容が多いので使えます。ただLinuxとWindowsのソケット関数の実装は違うそうです。
http://www.kt.rim.or.jp/~ksk/wskfaq-ja/
    • good
    • 0

http://cs.ecs.baylor.edu/~donahoo/practical/CSoc …
のページですかね。
# ソースコードだけのリンク貼られても、前提が判りません。
# ましてや、掲示されたリンクでは「改造前のHandleTCPClient()」がどんなモノかも判りません。

>引数に問題があるとエラーが出て先へ進めません。><

TCPEchoServer.cで使用しているHandleTCPClient()は「int型の引数1つ必要」と宣言されています。(TCPEchoServer.cの11行目)
コールしている箇所で貴方の改造したHandleTCPClient()を使用しようとしても、引数の数が合いませんのでコンパイルエラーとなるのでしょう。

>void HandleTCPClient(int clntSocket, int echoClntAddr) /* TCPクライアント関数処理 */
>struct clintIP echoClntAddr; /* クライアントのIPを取得 */

仮引数とローカル変数で同じ変数名は使用できません。
というか…後者は構造体clintIPという型のechoClntAddrという名前のローカル変数の宣言なんですが…

もしかしてclintIPというローカル変数にechoClntAddrを代入のつもりで書いていますか?
>if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE,clintIP,0)) < 0)
の使用例を見ると。
# ついでにソケット関数のrecv()は5つの引数取らないのでは?
# エラーはこっち…かな?
# エラーメッセージは下手な意訳なんぞせずに、そのまま記述しましょう。

さて、そうすると…clintIPというローカル変数はどんな構造体なんでしょうか???


なんというか、いろいろダメです。
# TCPEchoServer.cからはオープン済みのSocket番号のみ通知されるので、そこからクライアント側のIPアドレスやポート番号を取得するのは一手間かける必要があるでしょう。
# 具体的には調べていませんけど。<一手間について
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!