アプリ版:「スタンプのみでお礼する」機能のリリースについて

C言語初心者です。
既存のプログラムを直そうとしているのですが、ポインタの概念がいまいち理解できていないのか、修正した箇所がうまく動きません。
どうすればよいかをご教示いただけませんでしょうか。

元のプログラムは
void sub()
{
SOCKET s;
struct msg r_msg;
int time;
int cc;

cc = sub_recv(s, &r_msg, time);
・・・
}

void sub_recv(s,*msg,time)
{
unsigned char *pack;
int cc;
int len;

pack = (unsigend char *)msg

cc = recv(s, (char *)pack, len, 0);
if(cc < 0)
return(cc);
・・・
}

という感じでr_msg構造体にrecvで受け取ったものを入れて行きます。
ccにはrecv()の戻り値でサイズが返ってきて直後のifにはひっかかりません。
構造体の中でサイズが固定されているため、可変にするために以下のようにしたいです。

extern int buflen;
void sub()
{
SOCKET s;
unsigned char *r_msg;
int time;
int cc;

r_msg=(char *)malloc(sizeof(char)*buflen );
cc = sub_recv(s, r_msg, time);
free(r_msg);
・・・
}

void sub_recv(s,*msg,time)
{
unsigned char *pack;
int cc;
int len;

pack = (unsigend char *)msg
/*ここの代入は無意味と思いますがなくしても同様の結果のなので残してます。*/

cc = recv(s, (char *)pack, len, 0);
if(cc < 0)
return(cc);
・・・
}

しかし、このような修正で*r_msgにはrecv()で受け取った内容が入る気がするのですが、
ccには-1が入ってしまい、ifに引っかかって終了してしまいます。
この時のerrnoを見ても104が入り、connection reset by peerといった感じです。
recv()の第二引数にはこれがバッファが用意されてればいいと解釈しておりますが、
これではバッファが1バイトしかとれていないなどあるのでしょうか。
因に、send()がないからというのはありません。
キャストが間違えているなどもあるかもしれませんが、宜しくお願いします。

A 回答 (2件)

そういうものは省略されると想像するしか無いので、正しいかどうかの判断はできないのですが...




変更点は本当にここだけですか?(関数subのr_msgが構造体かunsigned char*かの違い)
変更前と後のソースファイル全部をdiffで比較しても、変更点はここだけですか?

Cのポインタの性質を考えれば、それだけの変更なら動作に違いはないはずです。
ポインタ自体には、実体が何型か、などという情報は含まれていないのですから。特に今回はchar*にキャストしているので、元が何型であったとしても、char*として扱われます。

また、recvは受け取るための関数であって、元に何が書かれていようが関係なく、受け取ったデータをそのポインタに順番に書き込むだけのはずです。


他に変わったんじゃないですか?
通信の仕様が変わって、バッファを可変にする必要がでてきたので、プログラムを変更してるのではないですか?

試しに、変更前のプログラムで 関数subの r_msg だけ変更して実行してみてください。
struct msg* r_msg;
r_msg=malloc(buflen) ;
sub_recv(s,r_msg,time) ;
以下、 r_msg.XXX → r_msg->XXXに変更

そちらでは正常に動作するはずです。
    • good
    • 0
この回答へのお礼

kmeeさん

ご回答ありがとうございます。
省略して申し訳ありませんでした。

>通信の仕様が変わって、バッファを可変にする必要がでてきたので、プログラムを変更してるのではないですか?
通信の仕様は変えていないと思います。
実際は send() で送るバッファも struct msg の構造体だったのですが、これを buflen で malloc した配列に変更しています。
修正しているのは自分だけなので、他は特に変更点はないはずです。
なので、send() 側を可変にしている状態で、recv() 側(今回質問させて頂いているソース)を修正前のソースですと、
struct msg 構造体でとってあるバッファ以下のものは受信できるのですが、当然それ以上だとプログラムが終了します。
なので、質問のような修正を行っております。

単純に recv() の動きを見たいと思い、以下のような事を試してみました。

void sub_recv(s,*msg,time)
{
unsigned char *pack;
int cc;
int len;
char buf[buflen]; //recv() 確認用バッファ。単純化する為に配列。

pack = (unsigend char *)msg
/*ここの代入は無意味と思いますがなくしても同様の結果のなので残してます。*/

cc = recv(s, buf, len, 0); //そのまま recv() に配列 buf を渡す
if(cc < 0)
return(cc);
・・・
}

他の部分で落ちるにしてもとりあえず recv() からは 1~len の値が返ってくるだろうと
期待したのですが、これでも cc には -1 が入ってしまうようなので、困惑しています。
アドバイス頂きましたものを参考に試してみたいと思います。
ありがとうございます。

お礼日時:2011/07/07 20:37

まず



> void sub_recv(s,*msg,time)
いまどき、こんな宣言は使いません。
別にプロトタイプ宣言がされているのでしょうか?
それとも、コンパイラやライブラリが古い仕様なのでしょうか?


> int len;

とありますが、そのlenに値が設定されていません。
ここに載せるときに省略しただけでしょうか?
そうでないなら、lenの値は不定です。何が入っているかわかりません。
len = 1 となっている可能性も0ではありません。recvの第三引数は、読み取る最大長を指定するものなので、 1バイトしかとれない、ということも有り得ます。



> extern int buflen;
> void sub()
...
> r_msg=(char *)malloc(sizeof(char)*buflen );

こういうのって、void sub(int buflen) と宣言して、引数で渡すのが普通で、externの変数を呼ぶなんてことは、それの方が明らかに便利、というときでもないかぎりやりません。

で、ここで確保した長さであるbuflenは、recvの第三引数として使いたいものではないでしょうか?
> void sub_recv(s,*msg,time)

void sub_recv(int s, struct msg *msg,int time,int len) とでも宣言して、
sub_recv(s,r_msg,time,buflen) とでも呼び出すのがいいのではないでしょうか?

> return(cc);
void型関数で値を返してはだめでしょ。
void型ならretrunだけにする。
値を返すなら、適切な型にしましょう。

この回答への補足

kmeeさん

早速のご回答ありがとうございます。

>void sub_recv(s,*msg,time)

ですが、これは

int sub_recv(SOCCKET s, unsigned char *msg, int time)

の間違いです。プロトタイプ宣言を忘れてしまい申し訳ありません。
質問を書いてるうちにccを戻そうと書いたところ、voidの修正も忘れてました。

>とありますが、そのlenに値が設定されていません。
>ここに載せるときに省略しただけでしょうか?

それぞれの変数には任意の値が入っていると仮定して下さい。説明不足で申し訳ありません。
ご指摘有り難うございます。

pack = (unsigend char *)msg

もセミコロンが抜けたりしていてすいません。

>こういうのって、void sub(int buflen) と宣言して、引数で渡すのが普通で、externの変数を呼ぶなんてことは、それの方が明らかに便利、というときでもないかぎりやりません。

おっしゃることは承知ですが、このbuflenをexternで使用したいと思っています。
ご提案のようにsub_recv()にbuflenを引数で渡す場合には、sub()内でなくそちらでmallocした方がいいということでしょうか?

今回伺いたかったのが、r_msgとmsgとpktの関係の部分についてだったので、他の部分を省いてしまったりでわかりずらく申し訳ありません。
なぜ修正後のものだとrecv()から-1が返ってきてしまうのか。そこが知りたいです。
r_msgに適当に文字列を入れてsub_recv()の中で*msgも*pktも期待値が取れるので、アドレスはちゃんと渡せているように思うのですが。
因に、lenに入る値はbuflenよりも小さいものと仮定してください。

わかりにくい質問で大変恐縮ですが、何卒宜しくお願いします。

補足日時:2011/07/07 07:07
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!