![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
初めて投稿させていただきます。
現在、Cにてあるクライアントプログラムを作成している者です。
構成は以下の通り。
《構成》
サーバ:PLC(シーケンサと書けば大体の方はわかりますか?)
クライアント:Linux Ubuntu9.10
通信方式:TCP/IP
《開発環境》
言語:C
IDE:eclipse
コンパイラ:gcc 4.x
《質問》
クライアントプログラムからASCIIデータをサーバへ送信し、サーバはクライアントから受信したASCIIデータに応答し、ASCIIデータ伝文を返信してきます。
このサーバからのASCIIデータ応答伝文をrecvfrom関数で受信し、応答伝文のASCIIデータを'buf'変数に格納し、標準出力関数で表示させるといったプログラムです。
このプログラムでは、ユーザ関数内でrecvfrom関数をコールしているのですが、ユーザ関数内でrecvfrom関数をコールした場合、受信データの先頭4byteしか受信できておらず、困っています。
ちなみに、main関数内でrecvfrom関数をコールすると、応答伝文全体のデータをきちんと受信できています。
ちなみに、サーバの応答ASCIIデータ伝文は、仕様通り(期待通り)のデータが返信されています。(ネットワークモニタ:wiresharkで確認済み)
recvfrom関数をコールする場所によって、変数に格納するデータ量が変わるといったことがあるのでしょうか。
ソースの一部を添付します。
参照の上、アドバイス等いただけないでしょうか。
《ソース》
◆mainソース
#include ...
:<-#include定義
int main{
:<-変数定義、変数初期値代入処理等
ユーザ関数1()コール<-ユーザ関数1内でソケット通信処理を動作させている。
ユーザ関数2()コール<-同上
}
◆ユーザ関数用ソース
#include...
:<-#include定義
unsigned char ユーザ関数名1;<-ユーザ関数プロトタイプ宣言
unsigned char ユーザ関数名2:<-同上
char 変数1[5];
char s_buf[4096];
char buf[4096];/*データ受信用バッファ*/
char 変数2[256];
size_t len;
long l;
int sock_fd;/*ソケット用ファイル記述子*/
struct sockaddr_in cl_addr;/*CPU用ソケットアドレス*/
socklen_t cl_len = 0;/*cl_addrのサイズ格納用*/
ssize_t n = 0;
unsigned char ユーザ関数1(char *引数1,…char *引数5){
:送信データ生成処理
//* ソケット作成 *//
if ((sock_fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
return 1;
}
//* 接続先定義*//
memset(&cl_addr, 0, sizeof cl_addr);
cl_addr.sin_family = AF_INET;/*プロトコル定義*/
cl_addr.sin_addr.s_addr = inet_addr("***.***.***.***"); /*IPアドレス定義*/
cl_addr.sin_port = htons(****);/*Port定義*/
//* 接続 *//
if (connect(sock_fd, (struct sockaddr *)&cl_addr, sizeof cl_addr) < 0) {
perror("connect");
return 1;
}
//* データ送信 *//
if(send(sock_fd, s_buf, strlen(s_buf), 0) < 0){
fprintf(stderr, "could not send message : %s\n", s_buf);
exit(EXIT_FAILURE);
}
printf("\nSendMessage\n%s\n",s_buf);
//* データ受信 *//
cl_len = sizeof cl_addr;
//*↓↓このrecvfrom関数でbuf内にサーバ応答伝文の先頭4byteのみが格納されている。↓↓*//
if (( n = recvfrom(sock_fd, buf, sizeof buf,0, (struct sockaddr *)&cl_addr, &cl_len)) < 0) {
perror("recvfrom");
return 1;
}
fprintf(stderr ,"TCP from addr = %s, port = %d\n",
inet_ntoa(cl_addr.sin_addr),
ntohs(cl_addr.sin_port)
);
A 回答 (6件)
- 最新から表示
- 回答順に表示
No.6
- 回答日時:
早い話が、こういうことが起きているのではないでしょうか。
#include <stdio.h>
void func(char *buf)
{
printf("%d\n", sizeof buf);
}
int main()
{
char buf[4096];
func(buf);
return 0;
}
No.4
- 回答日時:
No.2さんの回答で概ね合っているかと。
本筋から外れますが…
>int buf[4096];
>ならば、sizeof bufは4096を返しますが、
int型ならば4096はおそらく返されないでしょう。
char型で説明するつもりだったかと思われますが。
>ユーザ関数定義ソース内では、ユーザ関数1と2とあり、各関数で同一の変数名を使用したいと思い、グローバル宣言にしています。
>グローバル宣言とローカル宣言で何か違いでもあるのでしょうか。
スコープに違いがあります。
同じ名前のローカル変数を定義した場合、グローバル変数にはアクセスできませんのでご注意を。
# 名前空間で回避できるかも知れませんが…。
No.3
- 回答日時:
お~い, 元質問文中のソースと #1 へのお礼に書かれていることが矛盾してるぞ....
質問文中では
char buf[4096]; /*データ受信用バッファ*/
となってるから buf は配列のはずなのに, なんで「bufポインタ変数」になるの? どっちが正しいのか, はっきりしてください.
実際のソースと違うものを出すのは余計な混乱を招くだけなのでやめてください.
No.2
- 回答日時:
sizeof buf を 4096に変えたらデータを正しく取得できたとのこと、
原因はsizeofの使い方にあります。
bufをローカル変数として宣言した場合、
int buf[4096];
ならば、sizeof bufは4096を返しますが、
bufを明示的にメモリ獲得した場合、
int* buf = new int[4096];
sizeof buf はポインタのアドレス分のサイズ、
つまり4バイトしか返しません。
明示的にメモリを獲得した場合の
sizeofの使い方には注意しましょう。
No.1
- 回答日時:
4バイトのみ、というのが気になります。
考えにくいのですが、sizeof buf となっているところを
4096 に変えてみて試してはいかがでしょうか。
Vidocqさん、早速の回答ありがとうございます。
回答いただいたとおりに、’sizeof buf’部分を’4096’に変更し、
再度デバックしたところ、期待通りのデータをbuf変数に格納することができました。
ただ、なぜ具体的な数値を指定しただけで、きちんと格納できたのかが、
全く理解できません。
main関数内での実行とユーザ関数内での実行との違いとすれば、
bufポインタ変数の宣言を、main関数ではローカル宣言、ユーザ関数ではグローバル宣言しているぐらいなものです。
ユーザ関数定義ソース内では、ユーザ関数1と2とあり、各関数で同一の変数名を使用したいと思い、グローバル宣言にしています。
グローバル宣言とローカル宣言で何か違いでもあるのでしょうか。
ちなみに、デバッカでmain関数内でのコール時とユーザ関数内でのコール時で、recvfrom関数コール直前の’buf’変数内部の格納データを比べてみたところ、以下のような明らかな違いがありました。
◆main関数内コール
buf = '\000' <repeats 2500 times>"\236, \037\211", '\000' <repeats 25 times>"\370, \371\377\26 ...
◆ユーザ関数内コール
buf = 0x804d200 ""
sizeof bufを4096に変更した場合でも、ユーザ関数内コール時のbuf変数格納値はrecvfrom関数コールするまでは同じでした。
何か具体的な原因をつかみたいものですが、思い当たるところございませんでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・「I love you」 をかっこよく翻訳してみてください
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・昔のあなたへのアドバイス
- ・かっこよく答えてください!!
- ・あなたが好きな本屋さんを教えてください
- ・スタッフと宿泊客が全員斜め上を行くホテルのレビュー
- ・【大喜利】【投稿~8/27】 こんなガソリンスタンド二度と来るか!なぜそう思った?
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・【お題】動物のキャッチフレーズ
- ・【お題】甲子園での思い出の残し方
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・「それ、メッセージ花火でわざわざ伝えること?」
- ・自分用のお土産
- ・人生で一番お金がなかったとき
- ・一番好きなみそ汁の具材は?
- ・泣きながら食べたご飯の思い出
- ・ちょっと先の未来クイズ第1問
- ・ゴリラ向け動画サイト「ウホウホ動画」にありがちなこと
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
sprintfに同じ変数は使えるか
-
C言語について。
-
CStringをwchar_tに変換したい
-
'const char *' 型は 'char *' ...
-
3桁区切(コンマ)記号をつけ...
-
str系関数を使わずに二つの文字...
-
switch文で文字を比較すること...
-
干支のプログラム
-
文字列から空白を取り除きたい...
-
recvfrom関数の戻り値がおかし...
-
配列から指定するデータを取り...
-
const char** p;のとき、free(p...
-
ネットワークにつながっている...
-
RGBをCMYKに変換するプログラム
-
charからLPTSTRへの変換方法
-
PING JPEGファイルのExif規格の...
-
charでの計算?
-
文字列がNULLか空文字列かの判定
-
C言語のfor文です。 繰り返しの...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
C言語について。
-
charでの計算?
-
CStringをwchar_tに変換したい
-
charからLPTSTRへの変換方法
-
文字列から空白を取り除きたい...
-
C言語のfor文です。 繰り返しの...
-
atoi( ) の反対をやりたい
-
'const char *' 型は 'char *' ...
-
double型の値をchar配列に変換...
-
間接操作のレベルとは
-
テキストデータをそのままバイ...
-
型変換
-
3桁区切(コンマ)記号をつけ...
-
C言語のポインターで詰まっている
-
絶対パスからのファイル名の切...
-
str系関数を使わずに二つの文字...
-
配列をnビットシフトする
-
int main()の・・・
-
C言語の入力した文字を反転させ...
おすすめ情報