rshに関連してどなたか教えて下さい。
rsh-clientをC言語で書くには、具体的にどうしたらよいのでしょう?
例えば、
(1)socketをオープン。
(2)port=514でconnectを確立。
(3)sendで、"0\0"、ローカルユーザ、リモートユーザ、コマンドを送信。
(4)recvで受信。
とやっているのですが、毎回(3)まではエラーがなく、(4)で-1が返ってきます。私の理解が根本的に間違っているのかも知れません。
同じコマンドを、コマンドプロンプトからのrsh.exeでは実行可能です。
諸般の理由で、WindowsからLinux上のアプリを動かすのに、どうしてもCのコードの中にrshの機能を埋め込んで使いたのです。HTTP-clientのCのソースコードはよく見かけるし、自分でも書いていますが、rsh-clientは見たことがありません。
閉じた系で使うため、セキュリティ管理等は不要なので、使い慣れたrshが有り難いのですが...
是非よろしくお願いします。
A 回答 (4件)
- 最新から表示
- 回答順に表示
No.4
- 回答日時:
>そもそもrsh-clientの機能を実現するにはどのように書くのが一般的なんでしょうか?
一般的かどうか分かりませんが個人的な意見として
rsh-clientを自力実装することをあきらめ、
windows付属のrshをCreateProcessで起動し、プロセスの標準入出力をリダイレクトする。
という方法が良いのでは思われます。
参考情報
他のプロセスの出力を取得する
http://www.h4.dion.ne.jp/~fht/wptips/readprc.html
No.3
- 回答日時:
1,エラーコードが10054なのでWSAECONNRESET (10054) ですね。
>? 意味 : ピアによって接続がリセットされました。
ピア(サーバー)からの強制切断なので、送信しているデータは形式/内容ともに正しいものですか?
※)rshをethealでパケットキャプチャしながら実行して
rshの通信プロトコルを調べてみてください。
2,提示コードではコンパイルが通りません。
3,sendの戻り値のチェックが提示コードでは抜けています。
sendの戻値として-1の時があります。
4,以下の内容は手元の環境でwindows付属のrshを試してみた結果です。
手元の環境でwindows付属のrshコマンドを実行してみたところ、
rsh接続時に2つソケット(標準入出力用と標準エラー用)を作っています。
そして最初に標準エラー用のソケットの送信元ポート番号にNULL終端を付加しsendしています。
提示されたコードは最初に送信データとして"0\0"を送っていますが、
エラー用の送信元ポート番号を送る必要があるのではないのでしょうか?
以下のコードでソケットの送信元ポート番号を取得できます。
1,ローカル変数を2つ追加。
SOCKADDR_IN local;
int len;
2,iRC=send(sock,"0\0",2,0);の部分を以下のように変更。
len = sizeof(local);
/*ソケットの送信元ポート番号を取得*/
getsockname(sock,(const struct sockaddr*)&local,&len);
sprintf(t,"%u\0",ntohs(local.sin_port));
iRC=send(sock,t,strlen(t)+1,0);
以上、ご参考まで。
この回答への補足
たびたびすいません。
ご指摘に従って書き換えましたが、やはりrecvのところで-1が返ってきます。
コマンドとしては、取り敢えず"ls -l"を与えており、Windows付属のrsh.exeではちゃんと実行できます。
当方のコーディングは、根本的に間違っている可能性があります。
そもそもrsh-clientの機能を実現するにはどのように書くのが一般的なんでしょうか?
No.2
- 回答日時:
recv関数の戻り値が-1(SOCKET_ERROR)なので、サーバー側からの異常切断(RST)またはエラーだと思われます。
どのエラーなのかはWSAGetLastError関数で取得できますので確認してみてください。
例)
int n = recv(sock,buf,1024,0);
int code = WSAGetLastError();
Windows ソケットのエラー コード、値、および意味
http://support.microsoft.com/kb/819124/ja
recv Function
http://msdn.microsoft.com/en-us/library/ms740121 …
WSAGetLastError
http://msdn.microsoft.com/en-us/library/ms741580 …
この回答への補足
もう少し具体的に書きますと、書きのようにコーディングしています。
実際にやってみると、エラーコード10054が返ってきました。
----で囲んだ辺りの書き方が悪いのかも知れません。
引き続きアドバイスをお願いします。
int Exec_RSH(char *sCommand,char *sRet_str)
{ struct hostent *pHost;
WSADATA wsaData;
WORD wVersionRequired=0x0101;
SOCKADDR_IN addr;
SOCKET sock;
DWORD dwIP;
u_short PORT_NO=514;
int i=0,iRC=0;
char t[128],buf[4096];
int bFlag=1;
*sRet_str='\0';
if((WSAStartup(wVersionRequired,&wsaData))!=CLIENT_NO_ERROR) return(WSAGetLastError());
sock=socket(PF_INET,SOCK_STREAM,0);
if(sock==INVALID_SOCKET) return(-1);
if((dwIP=inet_addr(MY_HOST1))==INADDR_NONE){
if((pHost=gethostbyname(MY_HOST1))==NULL) return(-2);
dwIP=*((DWORD*)(pHost->h_addr));
}
addr.sin_family=AF_INET;
addr.sin_port=htons(PORT_NO);
addr.sin_addr.s_addr=dwIP;
if(connect(sock,(const struct sockaddr*)&addr,sizeof(addr))==SOCKET_ERROR) return(-3);
/*------------------------------------------------------*/
iRC=send(sock,"0\0",2,0);
strcpy(t,LOCAL_USER);
iRC=send(sock,t,strlen(t)+1,0);
strcpy(t,REMOTE_USER);
iRC=send(sock,t,strlen(t)+1,0);
strcpy(t,sCommand);
iRC=send(sock,t,strlen(t)+1,0);
/*------------------------------------------------------*/
while(bFlag){
i=recv(sock,buf,NNN-1,0);
if(i==0) break;
if(i==SOCKET_ERROR) return(WSAGetLastError());
buf[i]='\0';
strcat(sRet_str,buf);
}
closesocket(sock);
WSACleanup();
return(0);
}
No.1
- 回答日時:
はじめまして。
1,ビルド環境はwindows/linuxどちらですか?
winsockの場合はソケット操作を行う前にWSAStartupで初期化する必要がありますが。
2,文中のエラーがないとはどのようなことを仰っていますか?
3,Nagle アルゴリズムの影響を受けていませんか?
4,Etherealなどで実際にsend時にどのようなパケットが送信されたのか確認はしたのでしょうか?
この回答への補足
ありがとうございます。補足します。
1,ビルド環境はWindowsのVisual C++(をただのCコンパイラとして使っている)です。紙面の都合で書いていませんが、WSAStartupはsocketオープンの前にやってあります。リンク時にwsock32.libも指定しています。実際にHTTP-clientなどは、前述のようにして上手く動いています。
2,4,Ethereal?で確認した訳ではありませんが、
iRC=send(sock,"0\0",2,0);
等として、iRCの返り値が送信量と同じなことを確認しています。
3,すいません。仰っている意味が判りません。
今更何も素人がrshをCでコーディングしなくても...というご意見は大いにあるでしょうが、いろいろ事情(&好み)がありまして...エラーチャック、セキュリティ対策など細かいことは不要です。Linuxサーバ上の(かなり処理時間の掛かる)命令を実行させ、返ってくる結果をバッファで受信・結果判別できれば、目的達成です。
うまくいけば、同じよう記してLinux上でも動かしたいので、できるだけ汎用的な書き方が望ましい野ですが...よろしくお願いします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
TCP/IP通信時のサーバーからの受信
-
ソケットのrecvの戻り値が0
-
UDP通信におけるbind関数について
-
Connectエラーが出てしまう・・...
-
ソケットでクライアントのipア...
-
Socket通信の0バイト受信について
-
エクセル VBA でのCOMポート...
-
ソケットのクローズについて
-
サーバーソケットを開いたまま...
-
Winsockで接続待ちタイムアウト...
-
ソケットプログラミングに関す...
-
WinSockでの通信プログラムがう...
-
UdpClient 送信元のIPアドレ...
-
相手のIPアドレスを取得する方法
-
vxWorks6.4を使用してソケット...
-
Visual BASIC Express 2015 を...
-
Macターミナルで実行中のプログ...
-
プロダクションコードとは?
-
3のつく数字と3の倍数のみを表...
-
c言語のサイコロを100回振って...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
TCP/IP通信時のサーバーからの受信
-
エクセル VBA でのCOMポート...
-
VB6のwinsockでconnectできない
-
UDP通信におけるbind関数について
-
ソケットのクローズについて
-
ソケットのrecvの戻り値が0
-
Winsockで接続待ちタイムアウト...
-
UDP通信する時に、相手にどうや...
-
ソケットでクライアントのipア...
-
Connectエラーが出てしまう・・...
-
recv関数でフリーズしてしまう
-
UdpClient 送信元のIPアドレ...
-
Socket通信の0バイト受信について
-
同じLAN内パソコンのIPアドレス...
-
Winsockを使わずにVBでSocketを...
-
ソケットを用いた1対多通信につ...
-
ソケット通信 同じポート番号...
-
相手のIPアドレスを取得する方法
-
CreateFile関数でCOMポートが開...
-
送信したデータの一部が文字化...
おすすめ情報