
初めて投稿させていただきます。
現在、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で質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- C言語・C++・C# C言語で再起関数とポインタを用いて文字列反転をする方法がわかりません。 4 2023/04/29 20:32
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
構造体の各メンバにfor文からア...
-
プログラム
-
wake on lan のwindowsプログラ...
-
ひとつのプログラムにしたいの...
-
strchr() の第2引数はなぜ int ...
-
httpクライアントにて
-
CArray
-
配列をstrtokする方法
-
文字列を分解したいのですが・・・
-
c言語の境界調整について
-
文字列扱い方
-
8進数と16進数で表示するプロ...
-
エラーの意味
-
C言語について
-
puts関数やら
-
FILE*のfopenの素朴な疑問
-
文字を数値化する方法で詳しく...
-
[C++]ファイル出力について
-
書き込みデータのポインタのキ...
-
c言語のプログラミングについて...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
fgetsなどのときのstdinのバッ...
-
文字列から空白を取り除きたい...
-
間接参照のレベルが異なっています
-
C言語のfor文です。 繰り返しの...
-
CStringをwchar_tに変換したい
-
テキストデータをそのままバイ...
-
charからLPTSTRへの変換方法
-
atoi( ) の反対をやりたい
-
charでの計算?
-
配列をnビットシフトする
-
c++ 文字列を入力して、一文字...
-
'const char *' 型は 'char *' ...
-
c言語でユーザ関数を利用して入...
-
干支のプログラム
-
switch文で文字を比較すること...
-
char型からのバイト数取得
-
ネットワークにつながっている...
-
getchar()を int でとる理由...
-
間接操作のレベルとは
-
str系関数を使わずに二つの文字...
おすすめ情報