他マシン接続

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
わからんこ

他マシン接続

#1

投稿記事 by わからんこ » 13年前

http://dixq.net/forum/viewtopic.php?f=3&t=5386

ここを見つけて、他のパソコンとの通信を自分でもやってみたいと

思ったのですが、通信サンプルプログラムすら、うまく行きません。

ポート開放し、グローバルIPアドレスを相手に教え入力してもらうと、相手は接続に成功するのですが、

ホスト側の私は接続を待ちます。のままです。

私は勉強の為サンプルなどは手打ちしています。そのせいで、括弧の位置が違うなどで予期せぬ動作をすることなどが
ありますが、今回は自分の持っているノートパソコンとプライベートIPアドレスを渡し通信してみたところ、

うまくいったので、コードにミスはないと思います。

うまくいかない原因はなんでしょうか?

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: 他マシン接続

#2

投稿記事 by h2so5 » 13年前

「通信サンプルプログラム」とは何のプログラムでしょうか?
相手が接続に成功したとはどういう状況なのかも詳しく書いてください。

わからんこ

Re: 他マシン接続

#3

投稿記事 by わからんこ » 13年前

コード:

#include "DxLib.h"
#include <string.h>

#define CHAT_LINENUM		20	// チャット中の文字列を表示する行数
#define MAX_STRLENGTH		80	// チャットで1行で入力できる文字数
#define INPUT_LINE		21	// チャットで入力領域となる画面上の行位置
#define FONT_SIZE		16	// フォントのサイズ

int InputHandle ;			// 入力ハンドル
int StringY ;				// 文字列表示領域の次に文字列を表示する時の行位置
int NetHandle ;				// 接続相手のネットワークハンドル

char ScreenString[ CHAT_LINENUM ][ MAX_STRLENGTH + 1 ] ;	// 画面に表示中のチャット文字列


int ScreenStringAdd( char *AddString ) ;	// チャット文字列を追加する
int ScreenStringDraw( void ) ;			// チャットの現在の状態を画面に表示する


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
						LPSTR lpCmdLine, int nCmdShow )
{
	char Key ;

	// DXライブラリ初期化
	if( DxLib_Init() == -1 )
	{
		return -1 ;
	}

	// 入力領域と文字出力領域との境界線を引く
	DrawLine( 0 , CHAT_LINENUM * FONT_SIZE , 640 , CHAT_LINENUM * FONT_SIZE , GetColor( 255 , 255 , 255 ) ) ;

	// 接続を待つか接続をするか入力してもらう
	ScreenStringAdd( "接続を待つ場合はZキーを、接続をする場合はXキーを押してください" ) ;

	// どちらのキーが押されるか監視する
	{
		while( !ProcessMessage() )
		{
			if( CheckHitKey( KEY_INPUT_Z ) )
			{
				Key = 'Z' ;
				break ;
			}
			if( CheckHitKey( KEY_INPUT_X ) )
			{
				Key = 'X' ;
				break ;
			}
		}
	}

	// 押されたキーによって処理を分岐する
	switch( Key )
	{
	// 接続を待つ場合
	case 'Z':

		// 接続待ち状態にする
		PreparationListenNetWork( 9850 ) ;

		// 接続があるまで待つ表示
		ScreenStringAdd( "接続があるまで待ちます" ) ;

		// 接続があるまでここでループ
		while( !ProcessMessage() )
		{
			// 新しい接続があった場合はそのネットハンドルを保存する
			NetHandle = GetNewAcceptNetWork() ;

			// 新しい接続があった場合はループを出る
			if( NetHandle != -1 ) break ;
		}

		// 接続待ちを解除
		StopListenNetWork() ;

		break ;

	// こちらから接続をする場合
	case 'X' :
		{
			char StrBuf[ 81 ] , StrBuf2[ 81 ] ;
			IPDATA IP ;
			int i , j , k ;

			// 入力を行う
			while( !ProcessMessage() )
			{
				// 接続先のIPの入力を促す	
				ScreenStringAdd( "接続先のIPを入力してください" ) ;
				ScreenStringAdd( "入力は半角で各IP値は『.』で区切り、隙間は入れないで下さい" ) ;

				// IPの入力を行う
				KeyInputSingleCharString( 0 , INPUT_LINE * FONT_SIZE + 2 , 80 , StrBuf , FALSE ) ;

				// ピリオドが3つあるか調べる
				j = 0 ;
				for( i = 0 ; i < 80 ; i ++ )
				{
					if( StrBuf[ i ] == '.' ) j ++ ;
				}
				
				// もし3つピリオドがなかった場合は入力のし直し
				if( j != 3 )
				{
					ScreenStringAdd( "IP値の数が間違っています" ) ;
					continue ;
				}

				// 文字列からIPを抜き出す
				j = 0 ;
				k = 0 ;
				i = 0 ;
				while( !ProcessMessage() )
				{
					if( StrBuf[ i ] == '.' || StrBuf[ i ] == '\0' )
					{
						StrBuf2[ j ] = '\0' ;
						switch( k )
						{
						case 0 :IP.d1 = atoi( StrBuf2 ) ; break ;
						case 1 :IP.d2 = atoi( StrBuf2 ) ; break ;
						case 2 :IP.d3 = atoi( StrBuf2 ) ; break ;
						case 3 :IP.d4 = atoi( StrBuf2 ) ; break ;
						}
						k ++ ;
						if( k == 4 ) break ;

						j = 0 ;
					}
					else
					{
						StrBuf2[ j ] = StrBuf[ i ] ;
						j ++ ;
					}
					i ++ ;
				}

				// 接続中表示
				ScreenStringAdd( "接続中" ) ;

				// 接続を試みる
				NetHandle = ConnectNetWork( IP, 9850 ) ;

				// 接続に成功したらループから抜ける
				if( NetHandle != -1 ) break ;

				// 接続失敗表示
				ScreenStringAdd( "接続は失敗しました" ) ;
			}
		}
		break ;
	}

	// 接続成功表示
	ScreenStringAdd( "接続しました" ) ;

	// 文字列入力ハンドルを作成する
	InputHandle = MakeKeyInput( 80 , FALSE , FALSE , FALSE ) ;

	// 作成した入力ハンドルをアクティブにする
	SetActiveKeyInput( InputHandle ) ;

	// チャットループ
	while( !ProcessMessage() )
	{
		// 切断確認
		if( GetLostNetWork() == NetHandle ) break ;

		// 受信した文字列がある場合は受信する
		if( GetNetWorkDataLength( NetHandle ) > sizeof( int ) )
		{
			int StrLength ;
			char Message[81] ; 

			// 受信した文字列の長さを得る
			NetWorkRecvToPeek( NetHandle , &StrLength , 4 ) ;

			// 受信するはずの文字列長より受信されている文字数が少ない場合は
			// 何もせずもどる
			if( StrLength + 4 <= GetNetWorkDataLength( NetHandle ) )
			{
				// 文字列の長さを得る
				NetWorkRecv( NetHandle , &StrLength , 4 ) ;

				// メッセージを受信
				NetWorkRecv( NetHandle , Message , StrLength ) ;
				
				// 画面に表示
				ScreenStringAdd( Message ) ;
			}
		}

		// 文字列入力
		{
			// 文字列の入力が終っている場合は送信する
			if( CheckKeyInput( InputHandle ) == 1 )
			{
				char Message[ 81 ] ;
				int StrLength ;

				// 入力された文字列を取得する
				GetKeyInputString( Message , InputHandle ) ;

				// 入力された文字列の長さを送信する
				// +1 は終端文字('\0')を含めるため
				StrLength = lstrlen( Message ) + 1 ; 
				NetWorkSend( NetHandle , &StrLength , sizeof( int ) ) ;

				// 文字列を送信
				NetWorkSend( NetHandle , Message , StrLength ) ;

				// 自分のとこにも表示する
				ScreenStringAdd( Message ) ;

				// 入力文字列を初期化する
				SetKeyInputString( "" , InputHandle ) ;

				// 再度インプットハンドルをアクティブにする
				SetActiveKeyInput( InputHandle ) ;
			}

			// 画面に入力中の文字列を描画する
			DrawBox( 0 , INPUT_LINE * FONT_SIZE + 2 , 640 , 480 , 0 , TRUE ) ;
			DrawKeyInputString( 0 , INPUT_LINE * FONT_SIZE + 2 , InputHandle ) ;
			DrawKeyInputModeString( 640 , 480 ) ;
		}

		// 時間待ち
		WaitTimer( 32 ) ;
	}

	// 切断確認処理
	ScreenStringAdd( "切断しました" ) ;

	// 時間待ち
	WaitTimer( 3000 ) ;  

	DxLib_End() ;			// DXライブラリ使用の終了処理

	return 0 ;			// ソフトの終了
}
これなんですが、相手だけ接続に成功しましたとでます

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 他マシン接続

#4

投稿記事 by softya(ソフト屋) » 13年前

怪しい動作になると思うのであちこちのWaitTimer()とか沢山のrocessMessage()とかは避けたほうが良いと思います。
まずサンプルにあるコードそのままなどシンプルな環境でテストして下さい。

それとWireSharkなどパケットキャプチャを使いこなすことは通信系のデバッグのため必須の事項です。
パケットが外部に向かってちゃんと出て行っているのか?
外部からのパケットはちゃんと来ているのかを確認して下さい。

ご自身のルータなどやファイアウォールソフトなども疑う必要があります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

わからんこ

Re: 他マシン接続

#5

投稿記事 by わからんこ » 13年前

ご指摘の通り、パケットの状態を見てきましたが、外部からのパケットはきていませんでした。

接続側の接続状態から抜けれない理由がわかりましたが、

接続する側は、確かに私が開放したポートに接続することが出来ています。

送信側に接続できているのに、受信側は接続できないです。

受信側のプログラムにグローバルIPアドレス以外に何か与えないと、個別のパソコンまで

パケットが届かないのでしょうか?

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: 他マシン接続

#6

投稿記事 by h2so5 » 13年前

PreparationListenNetWork関数が成功しているのかが怪しいですね。
戻り値を確認してみてください。

わからんこ

Re: 他マシン接続

#7

投稿記事 by わからんこ » 13年前

戻り値は-1ですね・・・

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: 他マシン接続

#8

投稿記事 by h2so5 » 13年前

もしかして他のプロセスが9850番ポートを使用しているのかもしれません。

わからんこ

Re: 他マシン接続

#9

投稿記事 by わからんこ » 13年前

http://homepage2.nifty.com/natupaji/DxL ... m.html#N21

ここのサンプルなので、間違えはないと思うのですが・・・

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: 他マシン接続

#10

投稿記事 by h2so5 » 13年前

プログラムに間違いがなくても環境によって動かないことはあります。
相手側が接続できているのにこちら側で接続出来ていないということは、
こちら側で別のプロセスがポートを使用していて、それと相手側が接続している可能性があります。

わからんこ

Re: 他マシン接続

#11

投稿記事 by わからんこ » 13年前

ANHTTPでポートを開いているのですが、それがダメなんですかね?

これに相手から接続があると、相手のIPがでて接続中と、このソフトにはでるのですが

プログラムでは接続中にならないので・・・・

アバター
へにっくす
記事: 634
登録日時: 13年前
住所: 東京都

Re: 他マシン接続

#12

投稿記事 by へにっくす » 13年前

わからんこ さんが書きました:ANHTTPでポートを開いているのですが、それがダメなんですかね?

これに相手から接続があると、相手のIPがでて接続中と、このソフトにはでるのですが

プログラムでは接続中にならないので・・・・
・・・
ふつうサーバ自身がポートを開き待機するのです。
なぜ別プロセスで開いているポートを、他のプロセスが使用できると思ってるんですか?

#AnHTTPを実行しないでやってみてください。
written by へにっくす

わからんこ

Re: 他マシン接続

#13

投稿記事 by わからんこ » 13年前

友達と思考錯誤した上で、繋げる事が出来ました。

へにっくす さんの言うように別のプロセスが邪魔してたみたいでした。

まだ知識不足で、ありえない質問をしているかも知れませんが

これからもよろしくお願いします。

閉鎖

“C言語何でも質問掲示板” へ戻る