• 締切済み

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

ソケットプログラミングに関する質問です 最近ソケットプログラムに興味があり、勉強をしているのですが、 手始めにと下記の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で引っ張ってくればいいと思ったのですが、そういうわけでもないのです。

みんなの回答

回答No.2

ありもののクラスやライブラリを使う前に一度APIを叩くことを地道に実験されたほうが利益になるかと。ソケットの場合は特に。 以下に入門になかなか良いあきみちさんのサイトを載せておきます。もし開発環境がWindowsでない場合でもページ内にLinux用のものがあり有用です。 http://www.geekpage.jp/programming/winsock/ そしてもうすこし突っ込んだことを勉強してソケットオプションや、ソケット通信の仕様などを知るには以下のサイトが有名です。サンプルもシンプルに作られていて参考になりますが、残念ながらマルチスレッドとの併用などがあまり詳しく書かれていないのでご自分で実験されてみるとよろしいかと。このサイトはWinsockがメインで説明されていますがLinuxなどと共通している内容が多いので使えます。ただLinuxとWindowsのソケット関数の実装は違うそうです。 http://www.kt.rim.or.jp/~ksk/wskfaq-ja/

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/textcode.html のページですかね。 # ソースコードだけのリンク貼られても、前提が判りません。 # ましてや、掲示されたリンクでは「改造前の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アドレスやポート番号を取得するのは一手間かける必要があるでしょう。 # 具体的には調べていませんけど。<一手間について

関連するQ&A

  • ソケットプログラミング

    こんにちは。 ソケットプログラミングを勉強していて、音声を送りあえるIP電話らしきものを作ろうとしています。音声のやりとりは何とかできていますが、同時に文字列も送れるようにしたいです。ソケットをもう一つ作ればいいのではないかと思っていますが、実際に書いてみると、recv()の部分がうまく書けません。 音声データの送受信の部分は: while(1){ n=recv(sock,data1,N,0); //受信 if (n== -1){perror("recv");exit(1);} if(write(dsp, data1,n)==-1){perror("write"); exit(1);} //スピーカーから出力 n=read(dsp,data,N);  //マイクから入力 if (n== -1){perror("read");exit(1);} if(send(sock,data,n,0)==-1){perror("send");exit(1});} //送信 } 送信の時は n=read(0,tdata_2,N); send(sock_2,data_2,n,0); のように標準入力から文字列を読み込んで、data_2に格納し、新しく作ったソケットsock_2で送ればいいのですが、受信の時はどうしたらいいでしょうか。recv()をつかって、文字列と音声のデータを違うソケットで受け取って、違う配列に格納する方法があるでしょうか。 つまり、このような感じ(?): n1=recv(sock1,data1,N,0); //音声 n2=recv(sock2,data2,N,0); //文字列 とても悩んでますので、よろしくお願いします!!

  • プログラミング

    教えてください。以下のプログラムを修正してソケットを使った残高照会プログラムを作成。 関数searchdata(long key, char *dp, int size)を最後に追加する。 #include <stdio.h> /* for printf() and fprintf() */ #include <sys/socket.h> /* for recv() and send() */ #include <unistd.h> /* for close() */ #include <string.h> #define RCVBUFSIZE 32 /* Size of receive buffer */ int searchdata(long key, char *dp, int size); long id; void DieWithError(char *errorMessage); /* Error handling function */ void HandleTCPClient(int clntSocket) { char echoBuffer[RCVBUFSIZE]; /* Buffer for echo string */ int recvMsgSize; /* Size of received message */ /* Receive message from client */ if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0) DieWithError("recv() failed"); sscanf(echoBuffer, "%ld", &id); if (searchdata(id,echoBuffer,sizeof(echoBuffer))==EOF) { snprintf(echoBuffer,sizeof(echoBuffer),"%ld",0L); } if (send(clntSocket, echoBuffer, strlen(echoBuffer), 0) != strlen(echoBuffer)) DieWithError("send() failed"); close(clntSocket); /* Close client socket */ }

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

    こんにちは。 以前、この掲示板に質問させていただいた者です。 送信側から受信側へWinsockを利用し、jpeg,mpegファイルを送信したいのですが、プログラムを実行すると強制終了されてしまいます。以下に主要部分を記述します。 [送信側] FILE *fp; char fname[100]; printf("読み込み用ファイルを入力して下さい:"); scanf("%s",fname); if((fp = fopen(fname,"rb")) == NULL){ printf("入力ファイルをオープンできない。\n"); exit(1); } char send_buf[1025]; int nRet; int n; while(n = fread(send_buf,1,1024,fp) != -1){ sendto(theSocket,send_buf,n,0,(LPSOCKADDR)&saServer,sizeof(struct sockaddr)); } fclose(fp); closesocket(theSocket); [受信側] FILE *fp; char fname[100]; printf("書き込み用ファイルを入力して下さい:"); scanf("%s",fname); if((fp = fopen(fname,"wb")) == NULL){ printf("出力ファイルをオープンできない。\n"); exit(1); } char Recv_buf[1025]; char size; SOCKADDR_IN saClient; while(1){ size = recvfrom(theSocket,Recv_buf,1024,0,(LPSOCKADDR)&saClient,&nLen); fwrite(Recv_buf,size,1,fp); } fclose(fp); closesocket(theSocket); 受信側を先に起動し、送信側を起動。送信側で1024バイトずつ送信し、受信側でwhileの無限ループを用いて送信側からのデータを受信するプログラムにしたつもりです。しかし、送信側で読み込みファイルを指定すると強制終了されてしまいます。ファイルオープンの仕方がおかしいのでしょうか?また、上記のプログラムでは1024バイトずつ送信できるようになっていますでしょうか? よろしくお願いします。

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

    前回、ここで質問しましたが質問内容がきちんと記述できていなかったので、もう一度質問させていただきます。 [行いたいこと(概要)] PC1(送信端末)に保存されているファイル(jpeg,mpegファイル等)をUDPを使ってPC2(受信端末)へ送信し、PC2側でファイルを開くということです。 [現在、試していること] インターネットや本でもエコープログラミングしかサンプルプログラムがなく、実際どのようにすればよいか分かっていない状況です。以下に、プログラム内容を示します。 PC1(送信端末側) //ファイル名を入力し、ファイルをバイナリ形式で読み込み、sendto関数を用いて送信する。 FILE *fp; printf("送信ファイル名を入力:"); scanf("%s",&fname); if((fp = fopen(fname,"rb")) == NULL){ fprintf(stdout,"ファイルを開く際にエラーが発生しました\n"); exit(1); } while(!feof(fp)){    data = fgetc(fp)    sendto関数を用いて送信する } PC2(受信端末側) //ファイルポインタを用いて、受信ファイル名を記入しバイナリ形式で書き込む。while文は無限ループとし、PC1からのパケットを常時受け取る。 FILE *fp; printf("受信ファイル名を入力:"); scanf("%s",&fname); if((fp = fopen(fname,"wb")) == NULL){ fprintf(stdout,"ファイルを開く際にエラーが発生しました\n"); exit(1); } while(1){    receive関数を用いて受信する。 } 上記に示す様に作ろうと思っているのですが、実際に可能なのでしょうか? ソケットは、Windowsソケット、Linuxソケットどちらでもかまいませんので、よろしければサンプルプログラムも教えていただけないでしょうか? よろしくお願いします。

  • ソケットプログラミングとスレッドについて

    TCP/IPソケットを用いた通信プログラムを作成しています。その上でacceptする処理を専用スレッドにしており、accept後の受信処理をまた別のスレッドで処理しています。コンソールプログラムにおいてサーバとクライアントを用意しテストをしてみるとうまくいくのですが、MFCプログラムにおいて同じネットワーク処理を行ってみると、サーバ側へのconnectは成功するのですが、クライアント側からsendしたときにサーバ側でrecvの戻り値が必ず0にしかならず切断された状態になってしまいます。これはどういったときに発生すると考えられるでしょうか?ちなみにMFCが絡んでいるかどうかということは特にわかっておりません。 どなたかこのような経験をお持ちであればご教授お願い致します。

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

    こんにちは。 前回、質問しました「バード」という者です。 ソケットプログラミングについて質問します。 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プログラムやエコープログラムを、よく見かけるのですが・・・・

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

    コネクションの確立はlisten関数、accept関数、connect関数を用いて行い、パケット送信の場合は、UDPで送信するというプログラムを作成したいと思っています。 この場合、listen関数、accept関数、connect関数を使用する際は、TCPソケットをオープンするという形になるのでしょうか? それとも、listen,accept,connect関数は、UDPソケットオープンでよいのでしょうか? よろしくお願いします。

  • TCPのプログラミングで質問…というか確認しておきたいことが…

    このたびC言語でネットワークプログラミング(TCP)をしているのですが、気になったことがあったので、2点ほど質問させていただきます。 (1)WSock32のsendで一度に送信できる量は65535バイトと以前学んだのですが、受信側がrecvする前にどんどん65535バイト送信していったら受信側のソケットはどんどんいっぱいになってしまいますよね?その場合、限界はあるのでしょうか?また、一度にrecvできる量も65535バイトが限界なのでしょうか?もしそうだとしたら65535バイト以上データがあると取得しても残ってしまうんですか? (2)sendで大きなデータなどを送信した場合、受信側でrecvしたときに途中までのデータを受信してしまったりすることってありますか?たとえば、「"abcde"と送信したのに対し、受信側でrecvしたらとりあえず"abc"まで受信し、次のrecvで残りのデータを受信する」様なことってあるんでしょうか? すべてのデータがちゃんと送信されてからじゃないとrecvで取得することはできなくなっているんでしょうか… とてもとても分かりにくい文章で本当にすみません。 すべてとはいいません、少しでも情報があれば教えていただけませんでしょうか・・・ どうぞよろしくお願いいたしますm(_ _)m

  • ソケットのrecvの戻り値が0

    linuxにてソケットの勉強をしようと思い、 簡単なソケット通信のプログラムをCで組みました。 ret = recv(ID, Buff, sizeof(Buff), 0); といった感じでサーバ側を組んだのですが、 この戻り値retに0が入ることがあり、思うように動いてくれません。 私の認識だと、recvは受信するまで待ち、 受信したサイズを返すと思っているのですが、 それが0とは、いったいどういう意味を持つのでしょうか?

  • ソケットプログラミング(配列について)

    こんにちは。 この掲示板に、大変お世話になっています。 私は送信側から受信側へWindows上でUDPソケットを利用し、約3MByteのmpegデータを、1024Byteずつパケットに分割し送信しています。以下に、送信側のプログラムの概要を示します。 [送信側] ・配列[1025]確保し、fread関数を用いてファイルの読み込みを行い、sendto関数で受信側へ送信。 ・1024Byteずつ送出できているかを表示。 ・送出した1024Byteのパケット数を表示。 int n; int Num_n = 0; char send_buf[1025]; while((n = fread(send_buf,1,DATA_SIZE,fp)) != 0){ Num_n++; //1024Byteずつ送出できているかを表示させています printf("n:%dバイト\t",n); sendto(theSocket,send_buf,n,0,(LPSOCKADDR)&saServer,sizeof(struct sockaddr)); } //送出したパケット数を表示させています printf("%d個のパケットを送出しました\n",Num_n); <質問内容> 約3MByteのmpegを1024Byteずつ送信した場合、最後のパケットは、「n:4バイト」と表示されました。残りの1020バイト分は、どのような形で送信されているのでしょうか?確保した配列内に何も入っていない形で送信されているのでしょうか? また、私は送信側と受信側でスループットの計算を以下の式から算出しています。 送信側 (送信したパケット数×1024×8)/送信に要した時間 受信側 (受信したパケット数×1024×8)/受信に要した時間 送信したパケット数は3041個。 送信に要した時間=受信に要した時間です。 この場合、送信側での計算として・・・ (3041×1024×8)/送信に要した時間とするのか (3040×1024×8)+4/送信に要した時間とするのか どちらが正当なのでしょうか? よろしくお願いします。

専門家に質問してみよう