• ベストアンサー

ソケット通信において、送信相手のIPアドレスの取得の仕方。

検索したら struct sockaddr_in from; socklen_t fromlen = sizeof(from); recvfrom(s, buf, len, 0, (struct sockaddr *)&from, fromlen); このやり方で受信側で送信側のIPが取得できるはずなのですが、fromにnullが入っていて、取得できません。fromに送信相手のデータが入っていないわけですが、なぜでしょう。何かが足りていないのだとは思うのですがわかりません。

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

  • ベストアンサー
  • MovingWalk
  • ベストアンサー率43% (2233/5098)
回答No.1

この方法は試したことがないので、よくわかりませんが、 こちらは参考になりませんか。 http://www-cms.phys.s.u-tokyo.ac.jp/~naoki/CIPINTRO/NETWORK/caddr.html

参考URL:
http://www-cms.phys.s.u-tokyo.ac.jp/~naoki/CIPINTRO/NETWORK/caddr.html

その他の回答 (1)

  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.2

環境が示されてませんが、BSDSocketだと仮定して… recvfromは int recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); なので recvfrom(s, buf, len, 0, (struct sockaddr *)&from, fromlen); は recvfrom(s, buf, len, 0, (struct sockaddr *)&from, &fromlen); かと… また、戻り値とerrnoの値(defineされたマクロ名のほうがいいけど)を示していただければもっと正確な解答ができると思います。

morioka
質問者

お礼

>recvfrom(s, buf, len, 0, (struct sockaddr *)&from, fromlen); >は >recvfrom(s, buf, len, 0, (struct sockaddr *)&from, &fromlen); >かと… すいません。質問文が間違っていました。 recvfrom(s, buf, len, 0, (struct sockaddr *)&from, &fromlen); を使ってしました。 戻り値は受信するたびに変化して(だいたい12~44)、errnoの値は0(つまり正常・・・のはず)でした。 じゃあ何が問題だったかというと、私はIneternet domain stream型通信でプログラムを組んでいました(正確に言うと他の人が作ったのを引継いだのですが)。 間抜けな質問につき合わせてしまって申し訳ありません。mm(__)mm

関連するQ&A

  • UDP通信について

    UDP通信で困っています。 TCP/IP通信はすぐにうまくいったのですが、 UDPの簡単なサンプルがちゃんと動きません。 間違いがあればご指摘ください。 よろしくお願いします。 (クライアント側ソース int sock; struct sockaddr_in din; memset(&din, 0, sizeof(din)); din.sin_port = htons(50050); din.sin_family = AF_INET; din.sin_addr.s_addr = inet_addr("サーバーIP"); sock = socket(AF_INET, SOCK_DGRAM, 0); int buf = 12345; sendto(sock,(char*)&buf,sizeof(int),0,(struct sockaddr*)&din,sizeof(struct sockaddr_in)); (サーバー側ソース int sock; struct sockaddr_in sin; sock = socket(AF_INET, SOCK_DGRAM, 0); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(50050); sin.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { return(1); } struct sockaddr_in fromaddr; socklen_t len = sizeof(struct sockaddr_in); int buf; recvfrom(sock,(char*)&buf,sizeof(int),0,(struct sockaddr*)&fromaddr,&len); printf("recv:%d\n",buf);

  • TCP/IP通信型電話番号検索プログラムを作りたいです。

    TCP/IP通信型電話番号検索プログラムを作りたいです。 クライアントは以下のようで大丈夫みたいなのですが、サーバの方を修正しなければなりません。 この質問で「TCP/IP通信型大文字・小文字変換プログラム」を発見しました。 サーバー側プログラム #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #define SOCK_NAME "./socket" int main() { int i; int fd1, fd2; struct sockaddr_in saddr; struct sockaddr_in caddr; int len; int ret; char buf[1024]; if((fd1 =socket(AF_INET, SOCK_STREAM, 0)) < 0 ){ perror("socket"); exit(1); } memset((char *)&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr=INADDR_ANY; saddr.sin_port=htons(1357); unlink(SOCK_NAME); if(bind(fd1, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("bind"); exit(1); } if(listen(fd1,5) < 0 ) { perror("listen"); exit(1); } while(1){ len = sizeof(caddr); if((fd2 = accept(fd1, (struct sockaddr *)&caddr, &len)) < 0){ perror("accept"); exit(1); } fprintf(stderr, "Connection established: socket %d used.\n", fd2); while((ret = read(fd2, buf, 1024)) > 0 ){ fprintf(stderr, "read: &s\n", buf); for(i=0; i<ret; i++) if(islower(buf[i])) buf[i] = toupper(buf[i]); if(isupper(buf[i])) buf[i] = tolower(buf[i]); fprintf(stderr, "write: %s\n", buf); write(fd2, buf, 1024); } close(fd2); } close(fd1); return 0; } 先生によると、クライアントは同じもので良いそうです。 誰か、助けて下さい。

  • TCP/IP通信型大文字・小文字変換プログラム

    TCP/IP通信型大文字・小文字変換プログラムを作りたいです。 しかし、うまく2つのプログラムが接続されません。 恐らく、IPアドレスやホスト名の問題だと思います。 超初心者でそこのところをあまり理解していません。 どなたかプログラムの補足をお願いします。 概要は ・クライアント キーボードから文字列を入力し、サーバーに送信。 サーバーから送信された文字列を画面に出力。 ・サーバー クライアントから送信された文字列に対し、 大文字は小文字に、小文字は大文字に変換して返す。 クライアント側プログラム #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #define SOCK_NAME "./socket" int main() { struct sockaddr_in saddr; int soc; char buf[1024]; if ( (soc =socket(AF_INET, SOCK_STREAM, 0 ) ) < 0 ) { perror("socket"); exit(1); } memset((char *)&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr=inet_addr("192.168.1.1"); saddr.sin_port=htons(1357); if(connect(soc, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("connect"); exit(1); } fprintf(stderr, "Connection established: socket %d used.\n", soc); while(fgets(buf, 1024, stdin)){ if(buf[strlen(buf) -1] == "\n") buf[strlen(buf) -1] = "\0"; write(soc, buf, 1024); read(soc, buf, 1024); fprintf(stdout, "%s\n", buf); } close(soc); return 0; } サーバー側プログラム #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #define SOCK_NAME "./socket" int main() { int i; int fd1, fd2; struct sockaddr_in saddr; struct sockaddr_in caddr; int len; int ret; char buf[1024]; if((fd1 =socket(AF_INET, SOCK_STREAM, 0)) < 0 ){ perror("socket"); exit(1); } memset((char *)&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr=INADDR_ANY; saddr.sin_port=htons(1357); unlink(SOCK_NAME); if(bind(fd1, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("bind"); exit(1); } if(listen(fd1,5) < 0 ) { perror("listen"); exit(1); } while(1){ len = sizeof(caddr); if((fd2 = accept(fd1, (struct sockaddr *)&caddr, &len)) < 0){ perror("accept"); exit(1); } fprintf(stderr, "Connection established: socket %d used.\n", fd2); while((ret = read(fd2, buf, 1024)) > 0 ){ fprintf(stderr, "read: &s\n", buf); for(i=0; i<ret; i++) if(islower(buf[i])) buf[i] = toupper(buf[i]); if(isupper(buf[i])) buf[i] = tolower(buf[i]); fprintf(stderr, "write: %s\n", buf); write(fd2, buf, 1024); } close(fd2); } close(fd1); return 0; }

  • LinuxでのC言語通信プログラムについて

    サーバーとクライアントで足し算を行うプログラムを実行するとサーバーからの計算結果が返ってきません。ソースコードは以下に示します。 クライアントのプログラム #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> int main(void) { int sockfd ; int tolen , fromlen ; struct sockaddr_in to_address , from_address ; int result ; int ch[3] ; sockfd = socket(AF_INET,SOCK_DGRAM,0); to_address.sin_family = AF_INET ; to_address.sin_addr.s_addr = INADDR_ANY ; to_address.sin_port = htons(9734) ; tolen = sizeof(to_address); bind(sockfd , (struct sockaddr *)&to_address , tolen); printf("A = "); scanf("%d",&ch[0]); printf("B = "); scanf("%d",&ch[1]); sendto(sockfd , ch , sizeof(ch) , 0 , (struct sockaddr *)&to_address , tolen); recvfrom(sockfd , ch , sizeof(ch) , 0 , (struct sockaddr *)&from_address , &fromlen); printf("A + B = %d \n",ch[2]); close(sockfd); exit(0); } サーバーのプログラム #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> int main(void) { int ch[3] ; int sockfd ; int tolen , fromlen ; struct sockaddr_in to_address ; struct sockaddr_in from_address ; sockfd = socket(AF_INET,SOCK_DGRAM,0); to_address.sin_family = AF_INET ; to_address.sin_addr.s_addr = INADDR_ANY ; to_address.sin_port = htons(9734) ; tolen = sizeof(to_address); bind(sockfd , (struct sockaddr *)&to_address , tolen); while(1) { printf("server waiting\n"); recvfrom(sockfd , ch , sizeof(ch) , 0 , (struct sockaddr *)&from_address , &fromlen); ch[2] = ch[0] + ch[1] ; sendto(sockfd , ch , sizeof(ch) , 0 , (struct sockaddr *)&from_address , fromlen); } }

  • Winsockを利用した単純なファイル送信プログラムについて

    こんばんは。 何度もこの掲示板を利用させていただいている者です。 WinsockのUDPを用いて簡単なファイル送信プログラムを作っています。UDPを使わずに、TCPを使用したほうが良いのでは?とのご指摘をいただきましたが、まずは、UDPを利用した単純なファイル送信プログラムを作ってみたいと思っています。 しかし、送信側から受信側へファイルがうまく受信できていません。もしかしたら、送信側自体がきちんと送信できていないのかもしれません。 以下にそのプログラムの概要と内容を示します。 [概要] 送信側→受信側にUDPを用いて、送信側にあるjpegまたはmpegファイルを送信し、受信側でファイルを開く。 [プログラム概要] ・送信側 ファイルポインタを用いてファイルオープン fread関数とsendto関数を用いて1024バイトずつ送信 ・受信側 ファイルポインタを用いてファイルオープン whileの無限ループ内に、recvfrom関数とfwrite関数を用いて送信側からのデータを受信 [プログラムの内容] ・送信側 printf("読み込み用ファイルを入力して下さい:"); scanf("%s",fname); if((fp = fopen(fname,"rb")) == NULL){ printf("入力ファイルをオープンできない。\n"); exit(1); } char send_buf[1025]; int n; while(n = fread(send_buf,1,1024,fp) != -1){ sendto(theSocket,send_buf,n,0,(LPSOCKADDR)&saServer,sizeof(struct sockaddr)); } ・受信側 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); } ご指摘またはご教授をいただけたらと思います。 よろしくお願いします。

  • Linuxでsocket接続をしているのですが・・・。

    簡単なポートフォワードのプログラムを作ろうと思って、 下のようなプログラムを組んでみました。 struct sockaddr_in cli ; fd = SetupForClient(元IP, proto, port) ; で、クライアントから接続を待って clen = sizeof(cli) ; recvfrom(fd, recv_data, sizeof(recv_data), 0,(struct sockaddr *)&cli, &clen) ; でデータを受信して fd2 = ConnectToServer(先IP, proto, port) ; write(fd2, recv_data, sizeof(recv_data)) ; で反対側のNICにデータを書き出す・・・。 という基本的なものなのですが、書き出す側に接続しようとすると Connectの関数内で Address already in use というエラーが出てしまいます・・・。 fdを解放していないのかとも思ったのですが、再起動してもダメでした。 どういうことなのでしょうか・・・?

  • swith文について

    こんにちは。 switch文を用いて分岐を行っています。 以下のプログラムは、whileの無限ループ内にswitch文の分岐を行っています。while内にrecvfrom関数(ソケット通信用関数)を用いています。recv_Buf配列内をヌル文字まで走査し、文字列の長さによって分岐をしています。 while内のrecvfromによって、他端末から文字列を逐次受信しているのですが、この場合、switch文ではなくif文による分岐を行うべきなのでしょうか? また、breakを行うことで、whileの無限ループまで抜けることになるのでしょうか? switchの場合、breakを用いないと、実行したくないところまで実行してしまう可能性があるので、breakは必要だと思い以下のプログラムにしました。 よろしくお願いいたします。 [プログラム] while(1){   recvfrom(s2, recv_Buf, (int)sizeof(recv_Buf) - 1, 0, (SOCKADDR *)&from, &fromlen);   while(recv_Buf[len]!='\0')   len++;   switch(len){    case 3:     if(memcmp(recv_Buf,"END",3) == 0){      //処理     }     break;    case 5:     if(memcmp(recv_Buf,"START",5) == 0){      //処理     }     break;     case 12:     case 13:     case 14:     case 15:      if(memcmp(recv_Buf,"SEND_PACKET",11) == 0){       //処理      }      break;    } }

  • UDP通信について

    前回のことでかなり言われたので改変版を見てもらいたいと思います。 TCPと伝えていましたが今回、UDPに変えました。 ヘッダーはこのようになっております。 ==wsock.h== #include <Windows.h> #include <stdio.h> #pragma comment(lib,"WSock32.lib") #define PORT_NO 8000 ポート番号 #define SERVER_NAME "" enum MINE{ NONE, SERVER, CLIENT }; ソケット通信 class WSOCK{ private: WSADATA wsaData; SOCKET s; SOCKADDR_IN saddr; int rtn; int state; MINE mineFlg; char szStr[256]; エラーメッセージ用 u_short port; 変換後のポート番号 int fromlen; 受信したサイズ HOSTENT *lpHost; ホスト情報 ファイルディスクプリタをまとめた構造体 //→ソケット判別する為の管理情報 fd_set fds,readfds; public: char szRcvBuf[1024]; 受信バッファ char szSndBuf[1024]; 送信バッファ SOCKADDR_IN from; ソケットアドレス構造体 WSOCK(); ~WSOCK(); bool ServerRcv(); 受信 bool ServerSnd();送信 bool CliantRcv();受信 bool CliantSnd();送信 void SarverSet(); void ClientSet(); bool EnumMyIPAddress(); }; ==wsock.cpp== #include "wsock.h" コンストラクタ WSOCK::WSOCK(){ //WinSock初期化 rtn = WSAStartup(MAKEWORD(2,2),&wsaData); if(rtn != 0){ MessageBox(NULL,"WSAStartup失敗", "ERROR",MB_OK); state = -1; } ソケットを開く s = socket(AF_INET,SOCK_DGRAM,0); if(s<0){ MessageBox(NULL,"ソケットをオープンできません", "eRROR",MB_OK); WSACleanup(); state = 2; } 0で初期化 memset(&saddr,0,sizeof(SOCKADDR_IN)); saddr.sin_family = AF_INET;//アドレスファミリー saddr.sin_port = htons(PORT_NO);//ポート mineFlg = SERVER; サーバ側設定 if(mineFlg == SERVER) { SarverSet(); } if(mineFlg == CLIENT) {クライアント ClientSet(); } } WSOCK::~WSOCK(){ closesocket(s); ソケットのリソース解放 rtn = WSACleanup(); if(rtn == SOCKET_ERROR){ MessageBox(NULL,"WSACleanup失敗","ERrOR",MB_OK); state = -2; } } //受信 bool WSOCK::ServerRcv(){ 読み込み用fd_setの初期化 selectが毎回内容を上書きしてしまうので毎回初期化 memcpy(&fds,&readfds,sizeof(fd_set)); struct timeval timeout = {0,0};   //{1秒以上の部分()s、1秒以下の部分(ms)} fdsに設定されたソケットが読み込み可能になるまで待つ select(0,&fds,NULL,NULL,&timeout); ソケット読み込み可能データがある場合 if(FD_ISSET(s,&fds)){ fromlen = (int)sizeof(from); //nullで初期化 memset(szRcvBuf,'\0',sizeof(szRcvBuf)); //受信処理 rtn = recvfrom(s,szRcvBuf,(int)sizeof(szRcvBuf)-1,0, (SOCKADDR*)&from,&fromlen); if(rtn == SOCKET_ERROR){ MessageBox(NULL,"recvfromエラー","ERRoR",MB_OK); return false; } } szRcvBuf[rtn] | '\0';//NULLコード if(strcmp(szRcvBuf,"c_end") == 0){ MessageBox(NULL,"クライアントが接続を切りました","ERROr",MB_OK); return false; } return true; } 送信 bool WSOCK::ServerSnd(){ char buf[1024]; memset(buf,0,sizeof(buf)); //_snprintf:書式指定文字付きデータ書き込み _snprintf(buf,sizeof(buf),"data to port 8000"); //送信処理 rtn = sendto(s,szSndBuf,(int)strlen(szSndBuf)+1, 0,(LPSOCKADDR)&from, 送り先サーバ/クライアント sizeof(from)); サイズ if(rtn != (int)strlen(szSndBuf)+1){ MessageBox(NULL,"sendtoエラー","サーバーエラ",MB_OK); closesocket(s); WSACleanup(); return false; } return true; } 受信 bool WSOCK::CliantRcv(){ fromlen = (int)sizeof(from); //nullで初期化 memset(szRcvBuf,'\0',sizeof(szRcvBuf)); //受信処理 rtn = recvfrom(s,szRcvBuf,(int)sizeof(szRcvBuf)-1,0, (SOCKADDR*)&from,&fromlen); if(rtn == SOCKET_ERROR){ MessageBox(NULL,"recvfromエラー","ERRoR",MB_OK); return false; } szRcvBuf[rtn] | '\0'; //NULLコード if(strcmp(szRcvBuf,"s_end") == 0){ MessageBox(NULL,"接続を切りました","ERROr",MB_OK); return false; } return true; } 送信 bool WSOCK::CliantSnd(){ 送信処理 rtn = sendto(s,szSndBuf,(int)strlen(szSndBuf)+1, 0,(LPSOCKADDR)&saddr, 送り先サーバ/クライアント sizeof(saddr)); サイズ if(rtn != (int)strlen(szSndBuf)+1){ MessageBox(NULL,"sendtoエラー","erROR",MB_OK); closesocket(s); WSACleanup(); return false; } return true; } void WSOCK::SarverSet(){ saddr.sin_addr.s_addr = htonl(INADDR_ANY); ソケットにローカルアドレスを関連付ける if(bind(s,(LPSOCKADDR)&saddr, (int)sizeof(saddr)) == SOCKET_ERROR){ MessageBox(NULL,"bindエラー","er",MB_OK); closesocket(s); WSACleanup(); state = -3; } FD_ZERO(&readfds); FD_SET(s,&readfds); } void WSOCK::ClientSet(){    クライアント側設定    ホスト名からホスト情報を取得 lpHost = gethostbyname(SERVER_NAME); サーバのアドレスをセット memcpy(&(saddr.sin_addr), lpHost->h_addr_list[0], //サーバのアドレス lpHost->h_length); } となっております。

  • ソケット通信の受信処理について(マルチスレッド)

    今私はVisual Studio2010 C++で ソケット通信のプログラムをしているのですが、 クライアントから送ってくる文字をうまく受信できません。 接続は出来ています。 _beginthreadexでスレッドを作っています。 以下が受信の処理のスレッドになっています。 unsigned int __stdcall ThSend(void* pArg) {     CSocket_ServerDlg* pDlg = (CSocket_ServerDlg*)pArg; while(1){       char buf[256]; /* 受信するバッファ */ int buf_len; /* 受信したバイト数 */ buf_len = recv(pDlg->m_NewSoc,buf , RECVSIZE - 1, 0); if (buf_len != SOCKET_ERROR ){       buf[buf_len] = '\0'; /* 受信したバッファの後ろにNULLを付加する */       }       pDlg->m_xvEditResult += _T("Recv : ");       pDlg->m_xvEditResult += buf;       pDlg->m_xvEditResult += _T("\r\n"); } return 0; } "m_"はメンバ変数です。 以下がスレッド作成のソースになっています HANDLE hForth; unsigned int nForthID; hForth = (HANDLE)_beginthreadex(NULL, 0, ThSend , this, 0, &nForthID ); なぜ受信できないのか分からない状態です。 ではよろしくお願いします

  • パケット受信 recvfrom( )について

    お世話になります。 WinSockを用いてUDPパケット受信プログラムを作成しています。 環境はVC++です。ダイアログベースで、 STARTボタンを押すと受信開始します。 送信側よりパケットを1000個送信した場合、受信側では、 int num; SOCKET sock; char buf[1500]; //ソケットの設定は省略 while(1){ num = recvfrom(sock, buf, sizeof(buf), 0, NULL, NULL);  printf("%d",num ); if( num == SOCKET_ERROR){ break; } } recvfrom()で受信していますが、送信側で送信が完了しても while()を抜けないのか、応答なし(フリーズ)してしまいます。 printf()で表示してみると、 ちゃんと送信パケット個数回表示されています。 送信パケット数は変動するため、受信側のプログラムには 個数がわかりませんため、while()でループしています。 while()を抜ける条件はどうしたらいいのでしょうか? ちなみにrecvfrom()の戻り値として SOCKET_ERROR,0を指定してもエラーになります。 長くなりましたが、どうぞよろしくお願い致します。