• 締切済み

WinSockでの通信プログラムがうまくいきません

WinSockでの通信プログラムがうまくいきません。 使用言語はC++とDirectXです。 ローカルでの通信(ルータを介したパソコン同士)はうまくいくんですが、別の場所にあるPCとの通信ができません。 以下実際に使用している関数です。 関数はマルチスレッドで動かしています。 WSADATA mWsaData; SOCKET mSockYou,mSockI; struct sockaddr_in mAddr; struct sockaddr_in mServer; struct sockaddr_in mClient; void CNetwork::Init(){ int err = WSAStartup( MAKEWORD( 2, 0 ), &mWsaData ); if( err != 0 ){ ERROR_EXIT(); return; } //Socket初期化 mSockI = socket( AF_INET, SOCK_STREAM, 0 ); if( mSockI == INVALID_SOCKET ){ ERROR_EXIT(); return; } mPort = 0; memset( mName, 0, sizeof( mName ) ); } //Server側 void CNetwork::Accept(){ FILE* fp; fopen_s( &fp, "messageLog.txt", "w" ); mAddr.sin_family = AF_INET; mAddr.sin_port = htons( mPort ); mAddr.sin_addr.S_un.S_addr = INADDR_ANY; if( bind( mSockI, (struct sockaddr *)&mAddr, sizeof( mAddr ) ) ) fprintf_s( fp, "bind失敗\n" ); if( listen( mSockI, 10 ) != 0 ) fprintf_s( fp, "listen失敗\n" ); int len = sizeof( mClient ); SOCKET t = accept( mSockI, (struct sockaddr*)&mClient, &len ); if( t == INVALID_SOCKET ) fprintf_s( fp, "Accept失敗\n" ); mSockYou = t; fprintf_s( fp, "Accept終了\n" ); fclose( fp ); } void CNetwork::Connect(){ FILE* fp; fopen_s( &fp, "messageLog.txt", "a" ); fprintf_s( fp, "Connect開始\n" ); //ソケットの設定 mServer.sin_family = AF_INET; mServer.sin_port = htons( mPort ); mServer.sin_addr.S_un.S_addr = inet_addr( mName ); if (mServer.sin_addr.S_un.S_addr == 0xffffffff) { fprintf_s( fp, "hostbynameへ\n" ); struct hostent *host; host = gethostbyname( mName ); if ( host == NULL ) { return false; } mServer.sin_addr.S_un.S_addr = *(unsigned int *)host->h_addr_list[0]; } fprintf_s( fp, "Socketの設定完了\n" ); while( true ){ fprintf_s( fp, "connect()開始\n" ); if( connect( mSockI, (struct sockaddr *)&mServer, sizeof( mServer ) ) == 0 ){ fprintf_s( fp, "Connect完了\n" ); break; } else{ fprintf_s( fp, "Connect失敗\n" ); Sleep(100); } } fprintf_s( fp, "Connect終了\n" ); fclose(fp); } また、ログは下のように出ました。 //サーバ側 Accept失敗 //クライアント側 Connect開始 Socketの設定完了 connect()開始 Connect失敗 ご教授お願いします。

みんなの回答

回答No.10

NO.9の者です。 もし複数ルーターで分断されたLAN同士の通信ということでなく、ルーターを一段介しただけのクライアント・サーバー間通信であればNATブレイクは必要ないのでプログラムのバグでしょう。 出来ればネットワーク構成と端末接続構成を知りたいですね。

回答No.9

あなたのプログラムを読んではいないのですが、もし実験しているPC群が複数のルータで分けられた複数LANに散在しているのであればNATブレイクの必要アリかと・・・ P2P通信には必須の方法です。 ルーターR0以下に構成されているLAN内にあるソケット同士は普通にソケット関数をたたいてやれば通信できますが、ルーターR0とルーターR1で別々のLANが構築されていて、どのルーターもブリッジモードにはなっていないという前提(ルートのルーターにカスケード接続されたルーターとして動いている)ならば、R0以下のPCとR1以下のPCがP2P通信するにはまずNATブレイクでしょうね。NATピンホールパンチなどとも呼びますか・・

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.8

エラーについて書き忘れです。 >これは、関数呼び出しの間に割り込みがあったとのことですが、 >そのような処理の原因として何か考えられるものはあるでしょうか? >マルチスレッドにしたことが原因でしょうか? >(一定時間ごとに呼び出されるため、いちいち中断している可能性もありますし) WSAEINTRはWinsock1.1の停止型ソケットが WSACancelBlockingCallで取り消されたときに 発生するエラーです。 この関数は、現在非推奨になっていて、 一般にWinsock2では外部公開されない関数です。 MSDNにはGUIスレッドから内部で呼び出される 可能性があると記載がありますので、 GUIを使用すると発生するという可能性があります。 対応策としては、非同期ソケットにする必要が あるかもしれません。

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.7

反応が遅くなりましたが。。。 ちょこっと見てて気になったことを 書いておきます。 ・socketの作成 プロトコルが0で指定されていますが、 環境によって値が変わってしまうので、 TCPならIPPROTO_TCPを指定した方がよさそう。 ちなみに手持ちの環境で、winsock1なら 0はIPPROTO_IP、IPPROTO_TCPは6に なっています。 #VC2008環境。 ・Bind対象のアドレス 一番気になったところですが、 サーバ側のソケットは意図した アドレスにbindされていますか? ListenSocketのアドレス情報が、 mAddr.sin_addr.S_un.S_addr = INADDR_ANY; となっている為、意図したアドレスに bindされていないような気がします。 #ちなみにInAddrを使用する方法は #既に一般的ではありません。 ・マルチスレッド 標準ライブラリ関数と、_beginthread CreateThreadなどを併用すると メモリリークが発生するという問題が 確か数年前にMSから出ていたと思います。 Windows上で標準関数とマルチスレッドを 使用する場合は_beginthreadex() _endthreadex()を使いましょう。 ・クライアントについて クライアントで使用されているOSは何でしょうか? WindowsVista以降の場合、IPv6のアドレスが 割り当てられている可能性もありますが、 上記のコードはIPv4環境でしか使用できません。 #IPv6とIPv4が両方割り当てられていれば大丈夫かも。

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

返却されるエラーについては不明になってしまいますな…。 より低レベルな部分で確認が必要なのかも知れません。 パーソナルファイヤーウォールで拒否はしていませんよね? # 同一ネットワークの場合は無条件で受け入れ…とかになっているのかも知れませんし。 Wiresharkなどで接続要求が来ているか確認してみるのも必要かも知れません。

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

>クラス内の関数をマルチスレッドで動かすようにしています。Connectも同様です。 CNetwork::AcceptStart()の呼び出し元でインスタンスの破棄とかしていませんか? # デストラクタのshutdown()とか走ったから、「WSACancelBlockingCall()でキャンセルを…」というエラーが返却されている…とか考えられませんかね? というか…スレッドにしてもインスタンスを破棄する前に起動したスレッドを停止させないとなりませんよね? accept()が動作しないと、TerminateThread()で無理矢理殺すことになるかと思われますが…。 # _beginthread()で生成したモノをTerminateThread()で…だと、リソースリークとかしそうな気がします。 >一定時間main関数(またはメッセージ処理)を行わないとフリーズして止まってしまうので、このような形でサブスレッドで実行するようにしてます。 select()または、WSAAsyncSelect()やWSAEventSelect()を使うべき…かと。 とはいえ、ローカルネットワークでは問題ない(表面化していないだけの可能性もありますが)が、別の場所(外部ネットワーク経由?)だとダメ…というのも……。 # ルータのポート転送関係はチェック済みなんですよね?当然。

dai_directx
質問者

補足

>インスタンスの破棄 インスタンスの破棄は、アプリケーション自体を閉じたときにしか呼び出していないのでおそらくないとは思います・・・ >ルータのポート転送関係 ポートの開放のことでしょうか?ポートの開放でしたら、お互いに開放は行っています。

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

>accept()は接続要求されるまでそこで待機されると思っていたので、connect()とのタイミングなどとの関係はあるのですか? ブロッキングモードですので接続されるまで待つでしょうから、とりあえずは問題なさそうです。 # accept()がタイムアウト…なんてことはたぶん無いと思われますが。 サーバ側のマルチスレッド…はどのような動作になっているのでしょう? 呼び出し元のCNetwork::Accept()は接続されるまで戻ってきませんが、問題ない…んですよね? # 戻らない…ので、そのクラスを別のスレッドから破棄することもできない…ハズです。 accept()で、エラーがWSAEINTRとなると…WSACancelBlockingCall()でキャンセルしろ…と?

dai_directx
質問者

補足

サーバ側の動作は以下のようにしています。 クラス内の関数をマルチスレッドで動かすようにしています。Connectも同様です。 void CNetwork::AcceptStart(){  mThread = (HANDLE) _beginthread(      &CNetwork::AcceptLauncher,      0,      this); } static void AcceptLauncher(void* args){  reinterpret_cast<CNetwork*>(args)->Accept(); } DirectXの仕様なのか、一定時間main関数(またはメッセージ処理)を行わないとフリーズして止まってしまうので、このような形でサブスレッドで実行するようにしてます。

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

>accept関数の後、調べてみた結果WSAEINTRというエラーが発生していました。 listen()の直後にaccept()している様ですが… ねそのタイミングでクライアントがconnect()していますか? # ノンブロッキングでしょうから、タイムアウトまでaccept()で止まっているとは思われますが…。 複数接続できるようには作られていないっぽいので、listen()で10接続受け付ける様にするのは止めた方がいいかもしれません。 # まぁ、初回以外はaccept()されないのでクライアントはタイムアウトするでしょうが。 ということで、マルチスレッドにしても接続できるのは1クライアントだけです。 テストに使用した環境が接続保持状態のまま正しく開放できていなかったりしませんか? CNetworkクラスがどうなっているのか、同じポートで複数のインスタンスを作っていないか(その場合、bind()失敗ですが)、デストラクタで正しくSocket()の開放が行われているか…等々確認されてはどうでしょうか?

参考URL:
http://www.kt.rim.or.jp/~ksk/wskfaq-ja/
dai_directx
質問者

補足

>listen()の直後にaccept()している accept()は接続要求されるまでそこで待機されると思っていたので、connect()とのタイミングなどとの関係はあるのですか? >複数接続できるようには作られていない はい、このプログラムでは1つだけ接続が確立できればいいです。その場合、listen()では1つだけ受け付けるようにすればいいのですか? >テストに使用した環境が接続保持状態のまま正しく開放できていなかったりしませんか? 一応毎回CNetwork内のデストラクタで解放処理は行っています。 以下ソースコードです。 void CNetwork::Destroy(){  if( mType == TCP_SERVER ){   shutdown( mSockI, SD_BOTH );   closesocket( mSockYou );  }  //WinSock解放  WSACleanup();  ThreadClose();  DeleteCriticalSection( &mCSThread ); }

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.2

通信周りの関数で失敗した直後に WSAGetLastError関数を使用して エラーの詳細コードを取るとセッションが 確率できない理由がわかるかも知れません。 大抵の場合、ローカルエリアでつながるけど インターネットでつなげないのは、 ポートの解放がうまく行ってない場合が多いです。 ポートの設定はお使いのルータによって異なるので 確認してみてください。

dai_directx
質問者

補足

accept関数の後、調べてみた結果WSAEINTRというエラーが発生していました。 これは、関数呼び出しの間に割り込みがあったとのことですが、そのような処理の原因として 何か考えられるものはあるでしょうか? マルチスレッドにしたことが原因でしょうか?(一定時間ごとに呼び出されるため、いちいち中断している可能性もありますし)

回答No.1

ログの状況から見て、サーバー側のAccept失敗が問題だと感じます。 Acceptの失敗コードをとるのが良いのではないでしょうか? ちなみにAcceptが失敗する理由は、 http://software.aufheben.info/kouza/senior/kouza_socket3.html を参照されると、良いかもしれません。

関連する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);

  • winsockを使った通信方法

    送信側 #include <winsock2.h> #include <string.h> int main() { WSAData wsaData; SOCKET sock; struct sockaddr_in addr; int len; typedef struct recv { char Name[32]; int Flag; } RECV; RECV send; WSAStartup(MAKEWORD(2,0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); strcat(send.Name, "ABC"); send.Flag=12; len=sizeof(send); sendto(sock,(char *)&send,len, 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(sock); WSACleanup(); system("pause"); return 0; } 受信側 #include <stdio.h> #include <winsock2.h> #include <string.h> int main() { typedef struct rcv { char Name[32]; int Flag; } RECV; WSAData wsaData; SOCKET sock; struct sockaddr_in addr; int len; RECV rcv; WSAStartup(MAKEWORD(2,0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.S_un.S_addr = INADDR_ANY; bind(sock, (struct sockaddr *)&addr, sizeof(addr)); len=sizeof(rcv); recv(sock,(char *)&rcv, len, 0); printf("%s [%d]\n",rcv.Name,rcv.Flag); closesocket(sock); WSACleanup(); system("pause"); return 0; } winsockを使ったUDP通信プログラムで構造体データを送る事が出来ないのですが どこに誤りがあるのでしょうか? コンパイルは通ってるのですが、送信側を起動しても受信側で受け取ることが出来ていない状況です。

  • 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; }

  • ゲームの通信プログラムについてなんですが

    ボードゲームで対戦用にとTCP通信プログラムを導入したいのですがどうにもうまくいきません。 ゲームのところでつながっているにはつながっているんですが無限ループのように通信しているようなんです。 VisualStudio2010とwinsocketを使っております。 サーバーのプログラムはこうです。 void COMMU::SERWSA() { port = 6543; //WinSock初期化 rtn = WSAStartup( MAKEWORD(2,2), &wsaData); } void COMMU::SERSOCK() { listen_s = socket( AF_INET, SOCK_STREAM, 0); if(listen_s < 0)     { WSACleanup(); return; } //0で初期化 memset(&saddr, 0, sizeof(SOCKADDR_IN)); saddr.sin_family = AF_INET; saddr.sin_port = htons(port); saddr.sin_addr.s_addr = INADDR_ANY; if(bind(listen_s, (struct sockaddr *)&saddr, sizeof(saddr)) == SOCKET_ERROR)     { closesocket(listen_s); WSACleanup(); return; } } void COMMU::SERLIS() { //クライアントからの接続待ち状態にする if(listen(listen_s, 0) == SOCKET_ERROR) { closesocket(listen_s); WSACleanup(); return; } fromlen = (int)sizeof(from); s = accept(listen_s, (SOCKADDR *)&from, &fromlen); if(s == INVALID_SOCKET)     { closesocket(listen_s); WSACleanup(); return; }else{ inet_ntoa(from.sin_addr); } //リスンソケットはもう不要 closesocket(listen_s); MessageBox(NULL,"繋がった","読み込みエラー", MB_OK |MB_ICONERROR); } COMMU::~COMMU() { if(shutdown(s, SD_BOTH) != 0){ perror("シャットダウンに失敗しました\n"); } //ソケットのクローズ closesocket(s); //ソケットのリソース解放 rtn = WSACleanup(); if(rtn == SOCKET_ERROR){ fprintf(stderr, "WSACleanup失敗\n"); return; } printf("WSACleanup成功\n"); printf("サーバ終了\n"); } 続いてクライアントです。 void Client::CLWSA() { //ポート番号の入力 port = 6543; //数値に変換 //WinSock初期化 rtn = WSAStartup( MAKEWORD(2,2),//上位と下位を指定してWORDデータを返すマクロ &wsaData); } void Client::CLSOCK() { //ソケットを開く s = socket( AF_INET, //アドレスファミリ SOCK_STREAM, //TCP(接続型通信)で通信 0); //プロトコル(0:WinSockが自動的に判断) if(s < 0){ //perror("ソケットをオープンできません\n"); WSACleanup(); return; } //ホスト名からホスト情報を取得 lpHost = gethostbyname("PC○○"); if(lpHost == NULL)     { addr = inet_addr(szServer); //ネットワークアドレスからホスト情報を取得 lpHost = gethostbyaddr((char*)&addr,4,AF_INET); } if(lpHost == NULL)    { printf("ホスト情報取得エラー\n"); closesocket(s); WSACleanup(); getchar(); return; } } void Client::CLCONNE() { //0で初期化 memset(&saddr, 0, sizeof(SOCKADDR_IN)); saddr.sin_family = lpHost->h_addrtype; //ホストのアドレスファミリ saddr.sin_port = htons(port); saddr.sin_addr.s_addr = *((u_long *)lpHost->h_addr); //接続要求する if(connect(s, (SOCKADDR *)&saddr, sizeof(saddr)) == SOCKET_ERROR){ printf("connectエラー\n"); closesocket(s); WSACleanup(); getchar(); return; }else{ MessageBox(NULL,"つながりました","読み込みエラー", MB_OK |MB_ICONERROR); } } Client::~Client() { if(shutdown(s, SD_BOTH) != 0){ perror("シャットダウンに失敗しました\n"); } //ソケットのクローズ closesocket(s); //ソケットのリソース解放 rtn = WSACleanup(); if(rtn == SOCKET_ERROR){ fprintf(stderr, "WSACleanup失敗\n"); return; } printf("WSACleanup成功\n"); printf("クライアント終了\n"); } です。 わかりにくいかと思いますがかなり困ってます・・・ 回答よろしくお願いします。

  • 延々と受信し続けるwinsockのrecv

    以下のサーバープログラムを用いて、 (acceptしたらスレッド作成し、作成が終ったということをクライアントに知らせるために文字列送信後受信待機している) #include <winsock2.h> #include <vector> #include <process.h> #include <algorithm> char *Ver = "0.00"; using namespace std; unsigned __stdcall Patch( void *Sock ); int main() { ----WSADATA wsaData; --------WSAStartup( MAKEWORD(2,0), &wsaData ); ----SOCKET RecvSock = socket( AF_INET, SOCK_STREAM, 0 ); ----SOCKET SendSockBuf; ----vector<SOCKET> SendSock; ----fd_set ConnectFds, SubConnectFds; ----struct sockaddr_in Recv, Send; ----int len = sizeof(Send); ----Recv.sin_family = AF_INET; ----Recv.sin_port = htons(55555); ----Recv.sin_addr.S_un.S_addr = INADDR_ANY; --------bind(RecvSock, (struct sockaddr *)&Recv, sizeof(Recv) ); ----FD_ZERO( &SubConnectFds ); --------FD_SET( RecvSock, &SubConnectFds ); ----listen( RecvSock, 5 ); ----vector<unsigned int> thID; ----vector<HANDLE> hTh; ----struct timeval tv; --------tv.tv_sec = 0; --------tv.tv_usec = 0; ----while(1) ----{ --------memcpy( &ConnectFds, &SubConnectFds, sizeof(fd_set) ); --------select( 0, &ConnectFds, NULL, NULL, &tv ); --------if ( FD_ISSET(RecvSock, &ConnectFds) ) --------{ ------------SendSockBuf = accept(RecvSock, (struct sockaddr *)&Send, &len); ------------if( SendSockBuf != INVALID_SOCKET) ------------{ ----------------SendSock.push_back( SendSockBuf ); ----------------thID.push_back( hTh.size() ); ----------------hTh.push_back( (HANDLE)_beginthreadex(NULL, 0, Patch, &SendSock[hTh.size()], 0, &thID[hTh.size()]) ); ------------} --------} ----} ----closesocket(RecvSock); ----WSACleanup(); ----return 0; } unsigned __stdcall Patch( void *Sock ) { ----SOCKET *SendSock = (SOCKET *)Sock; ----send( *SendSock, Ver, 5, 0 ); ----char Str[5]; ----while( Flag == 0 ) ----{ --------recv( *SendSock, Str, 5, 0 ); ----} ----closesocket( *SendSock ); ----return 0; } 以下のようなクライアントプログラムで文字を送信すると、 #include <WinSock2.h> using namespace std; void main() { ----WSADATA wsaData; --------WSAStartup( MAKEWORD(2,0), &wsaData ); ----SOCKET Sock = socket( AF_INET, SOCK_STREAM, 0 ); ----struct sockaddr_in Addr; --------Addr.sin_family = AF_INET; --------Addr.sin_port = htons(55555); --------Addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); ----connect( Sock, (struct sockaddr *)&Addr, sizeof(Addr) ); ----char str[5]; ----recv( Sock, str, 5, 0 ); ----send( Sock, "0.00", 5, 0); ----shutdown( Sock, 2 ); ----closesocket( Sock ); } クライアントプログラムは終了しているのにサーバープログラムは"0.00"を受信し続けます。 どこがおかしいのか分からないので教えてください

  • UNIXでのTCP/IP

    クライアントとサーバの通信をするプログラムを作っているのですが gethostbyaddr()でホスト名を得てそれをprintf()からホスト名を表示させたいのです。 //サーバ側 #define MAXPENDING 5 void DieWithError(char *errorMessage); void HandleTCPClient(int clntSocket); char * ResolveAddr(unsigned long addr) { struct hostent *host; host = gethostbyaddr((char *)&addr, sizeof(addr),AF_INET); if (host == NULL) { fprintf(stderr, "gethostbyaddr() failed"); exit(1); } return host->h_name; } int main(int argc, char *argv[]) { int servSock; int clntSock; struct hostent *host; struct sockaddr_in echoServAddr; struct sockaddr_in echoClntAddr; unsigned short echoServPort; unsigned int clntLen; if(argc != 2) { fprintf(stderr, "Usage: %s <Server Port>\n", argv[0]); exit(1); } echoServPort = atoi(argv[1]); if((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))<0) DieWithError("socket() failed"); memset(&echoServAddr, 0, sizeof(echoServAddr)); echoServAddr.sin_family = AF_INET; echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); echoServAddr.sin_port = htons(echoServPort); if(bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr))<0) DieWithError("bind() failed"); if(listen(servSock, MAXPENDING)<0) DieWithError("listen() failed"); for (;;) { clntLen = sizeof(echoClntAddr); if((clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr,&clntLen))<0) DieWithError("accept() failed"); ResolveAddr(echoClntAddr.sin_addr.s_addr); printf("Handling client %s\n", host->h_name); HandleTCPClient(clntSock); } } コンパイルするとクライアントからIPアドレスを渡した際にセグメンテーション違反になるのですがどこが間違っているのか分かりません。

  • コンソールアプリケーションで通信したい

    クライエントプログラムを起動もしていないのに、アクセスがありましたと表示されます。 どこが悪いのか教えてくださいませんでしょうか? サーバー側 #include <stdio.h> #include <winsock2.h> int main() { WSADATA wsaData; LPHOSTENT host; SOCKET s; SOCKADDR_IN name = { AF_INET } , client; int client_addr=sizeof(SOCKADDR_IN); SOCKADDR_IN addr,addr2; addr.sin_family=AF_INET; addr.sin_port=2048; IN_ADDR ip;//実際と異なるアドレス ip.S_un.S_un_b.s_b1=180; ip.S_un.S_un_b.s_b2=328; ip.S_un.S_un_b.s_b3=9; ip.S_un.S_un_b.s_b4=56; addr.sin_addr=ip; WSAStartup(2 , &wsaData); s = socket(AF_INET , SOCK_STREAM , 0); bind(s , (SOCKADDR *)&addr , sizeof(addr)); listen(s , 1); int sizeaddr2=sizeof(addr2); accept(s , (SOCKADDR *)&addr2 , &sizeaddr2); printf("アクセスがありました\nポート %d : アドレス = %s\n" ,addr.sin_port , inet_ntoa(addr.sin_addr)); shutdown(s , SD_BOTH); closesocket(s); WSACleanup(); getchar(); return 0; } クライエント側 #include <stdio.h> #include <winsock2.h> int main() { while(1) { WSADATA wsaData; SOCKET s; WSAStartup(2 , &wsaData); s = socket(AF_INET,SOCK_STREAM , 0); IN_ADDR ip;//実際と異なるアドレス ip.S_un.S_un_b.s_b1=180; ip.S_un.S_un_b.s_b2=328; ip.S_un.S_un_b.s_b3=9; ip.S_un.S_un_b.s_b4=57; SOCKADDR_IN addr; addr.sin_family=AF_INET; addr.sin_port=2048; addr.sin_addr=ip; connect(s,(PSOCKADDR)&addr,sizeof(SOCKADDR)); send(s,"OK",3,0); shutdown(s , SD_BOTH); closesocket(s); WSACleanup(); } return 0; }

  • 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; } 先生によると、クライアントは同じもので良いそうです。 誰か、助けて下さい。

  • Winsockについての質問

    Winsockで、「GET / HTTP/1.1」というリクエストを「127.0.0.1(自分自身)」に送って(サーバーはAPACHE2)ドキュメントルートにある「index.html」を見る。 というプログラムを作ったのですが、受信ができません。 受信できるにはどうすればいいか教えてください。 尚以下がそのプログラムです。 #include<stdio.h> #include<winsock2.h> int main(){ SOCKET hsock; struct sockaddr_in serverOption; char buf[1024]; int Error; int func_Error; WSADATA wsadata; func_Error=WSAStartup(MAKEWORD(2,0),&wsadata); if(MAKEWORD(2,0)!=wsadata.wVersion){ fprintf( stderr, "Winsock version error\n"); return -1; } hsock=socket(AF_INET,SOCK_STREAM,0); if(!hsock){ printf("ソケット作成エラー"); } serverOption.sin_family=AF_INET; serverOption.sin_addr.s_addr=inet_addr("210.81.150.5"); serverOption.sin_port=htonl(80); func_Error=connect(hsock,(struct sockaddr *)&serverOption,sizeof(serverOption)); if(!func_Error){ printf("接続エラー"); } func_Error=send(hsock,"GET / HTTP/1.1",strlen("GET / HTTP/1.1"),0); if(!func_Error){ printf("データが送れない。残念ですた"); } Error=recv(hsock,buf,sizeof(buf),0); if( Error <= 0) { printf("受信不可能"); return -1; } buf[Error]='\0'; printf("%s",buf); closesocket(hsock); WSACleanup(); return 0; }

  • Cプログラム UDP送信の送信データに関して

    以下の2つのプログラムでの質問なのですが、 #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") int main() { WSADATA wsaData; SOCKET sock; struct sockaddr_in addr; WSAStartup(MAKEWORD(2, 0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(3054); addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.3 "); sendto(sock, "\x42\42\0\0\0\0\2\0\1\2\x44\x33\5", 13, 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(sock); WSACleanup(); return 0; } と #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") int main() { WSADATA wsaData; SOCKET sock; struct sockaddr_in addr; WSAStartup(MAKEWORD(2, 0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(3054); addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.3 "); sendto(sock, "HELLO", 5, 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(sock); WSACleanup(); return 0; } について、送信データ部分に「¥」入ることによって、送信プロセスでどのような処理がなされているのですか? ¥~¥までで1バイトということで処理してくださいね、と処理系?に指示しているのですか? また、「¥」はC言語ならではの表記の仕方なのですか?少し、伝えるのが難しいですが、何でもいいのでご回答頂けませんか?宜しくお願いします。

専門家に質問してみよう