バイナリデータの送信

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

バイナリデータの送信

#1

投稿記事 by shiro4ao » 15年前

TCPソケットでバイナリデータを贈りたいと思います。
そのままでは良くないと思い一応,送るバイナリデータは
簡易的に暗号にしたいともいます。
復号化のためデータの区切りをはっきりさせないといけないので
データの最初に"a"最後に"z"を付けておくります。
例)
dataという文字(テキストですが、バイナリだと思ってください)を送る場合
a(dataをXORで暗号にしたもの)z
というデータを送り、受信側で解析してdataというデータを受け取りたいのです。

以下のコードではテキストデータの送信は成功したのですが、
バイナリデータになると、おかしなデータが送られているようでした。
何か解決方法はありますか?
それとも根本からおかしいのでしょうか?


//送信側
sendex(SOCKET s,char FAR * buf, int len,int flags )
{
int i,ret,n=0;
char msg[4000];
memset(msg,'\0',4000);

//XORを用いて簡易的に暗号にする
for(i = 0; i < strlen(buf); i++) buf = ~buf;

        //データの始まりに"a"、終に"z"を書き込み、区切りとして使う
strcat(msg,"a");
strcat(msg,buf);
strcat(msg,"z");

ret=func(s,msg,strlen(msg), flags);

return ret;
}



//受信側
recvex (SOCKET s, char FAR * buf, int len,int flags )
{
int ret,ret2=0,i;
char *size,tmp1[4000],*tmp2,test[1000];
int n=0;
memset(test,'\0',1000);


ret= func(s,tmp1,len, flags);
if(ret<1) return 0;

int limit =ret;
int mark=limit;
int pos=0;

while(pos<limit){
//aをさがす
if(tmp1[pos]=='a'){
mark=pos;
}


//zを探す
if(tmp1[pos]=='z'){
int pos03=pos;
pos=mark;

if(pos03>pos){
//データ部の切り出し
n=pos03-pos-1;//-14;
tmp2=new char[n];
memcpy(tmp2,&tmp1[mark+1],n);

//XORで復号化
for(i = 0; i < n; i++) tmp2 = ~tmp2;

memset(buf,'\0',sizeof(buf));
memcpy(buf,&tmp2[0],n);
strcpy(&buf[n],"\0");

}else{
return n;
}

pos=pos03;
}

pos++;
}

//確認用メッセージボックス
strcat(test,"-");
strcat(test,buf);
strcat(test,"-");
MessageBox(NULL,test,"bufの中",NULL);


return n;
}

Poco

Re:バイナリデータの送信

#2

投稿記事 by Poco » 15年前

根本的に間違っています。

・送信側:
 ・送信データに0が入っていた場合は?
  例えばバイナリデータとして、0をいくつか送ろうとしても、
  strcat()では、送信バッファmsgにデータは入りません。

・受信側:
 ・暗号化したデータがaやzとなった場合は?
  例えば受信データ本体の途中にzが含まれていると、そこで受信が終りになります。
  これは望んだ結果ではないですよね?
 ・受信時に開始記号aや終端記号zがない場合は?
  一回のrecv()で全ての送信データが取得できるとは限りません。
  send()で100kByte送信しても、recv()では50kByteしか受信できない可能性もあります。
・その他:
 ・XOR?
  ビット反転しているだけですよね?
  コメントかコードがおかしいです。

shiro4ao

Re:バイナリデータの送信

#3

投稿記事 by shiro4ao » 15年前

ご回答ありがとうございます。
XORの部分はコメントが間違っています。ビット反転をしています。

送信側にも受信側にも問題だらけの実装だったのですね・・・・
どのような設計にすればいいでしょうか?
実装ではなく大まかな方法を教えていただければ幸いです。

へろりくしょん

Re:バイナリデータの送信

#4

投稿記事 by へろりくしょん » 15年前

最初に送りたいバイト数を送って、その後に実際のデータを送ればいいだけでは無いでしょうか。

受信側は、最初に送られてきたバイト数だけ受信すればいいことになりますね。

HTTPなんかは概ねこんな感じの仕様になってます。
とりあえず、既存のプロトコルのまねをするところから始めると失敗が少ないと思いますよ。

shiro4ao

Re:バイナリデータの送信

#5

投稿記事 by shiro4ao » 15年前

へろりさんありがとうございます。
先に贈りたいサイズを送ってその後、データを送信するようにしてみたのですが、
受信側がクラッシュするようでした。
サイズの受信までは上手く行っているようでした。
なにがまずかったのでしょうか?

//送信側
sendex(SOCKET s,char FAR * buf, int len,int flags )
{
int i,ret,n=0;
char msg[4000];
memset(msg,'\0',4000);

   //データサイズの始まりに"a"、終に"z"を書き込み、区切りとして使う
itoa(len,size,10);
strcat(msg,"a");
strcat(msg,size);
strcat(msg,"z");

//サイズを送信
ret=func(s,msg,strlen(msg), flags);

//データ本体を送信
ret=func(s,buf,len, flags);

return ret;
}



//受信側
recvex (SOCKET s, char FAR * buf, int len,int flags )
{
int ret,ret2=0,i;
char *size,tmp1[4000],*tmp2,test[1000];
int n=0;
memset(test,'\0',1000);

   //まずデータサイズを調べてbufに入れる
ret= func(s,tmp1,len, flags);
if(ret<1) return 0;

int limit =ret;
int mark=limit;
int pos=0;

while(pos<limit){
//aをさがす
if(tmp1[pos]=='a'){
mark=pos;
}


//zを探す
if(tmp1[pos]=='z'){
int pos03=pos;
pos=mark;

if(pos03>pos){
//データ部の切り出し
n=pos03-pos-1;//-14;
tmp2=new char[n];
memcpy(tmp2,&tmp1[mark+1],n);

//XORで復号化
for(i = 0; i < n; i++) tmp2 = ~tmp2;

memset(buf,'\0',sizeof(buf));
memcpy(buf,&tmp2[0],n);
strcpy(&buf[n],"\0");

}else{
return n;
}

pos=pos03;
}

pos++;
}


//ここからがデータ本体の受信
size=atoi(buf);

ret=0;
memset(buf,'\0',sizeof(buf));

    //文字を受け取って指定サイズまでbufの後ろにくっつけていく
while(size>=ret){
n=func(s,tmp1,4000,flags);
memcpy(&buf[ret-1],&tmp1[0],n);
ret=n+ret;
}



return n;
}
画像

へろりくしょん

Re:バイナリデータの送信

#6

投稿記事 by へろりくしょん » 15年前

ざらっとしか見てませんが、関数 recvex() 内の

>//XORで復号化
>for(i = 0; i < n; i++) tmp2 = ~tmp2;

の行は必要ですか?
送信側では暗号化されてないようですが。


それと、若干スパゲッティ化してますので、処理を大きく切り分けるように心がけると、プログラムの見通しもよくなり、よく分からないバグも減りますよ。

閉鎖

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