UDP通信について

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

UDP通信について

#1

投稿記事 by こっこ » 12年前

現在windows8 でUDPの通信プログラムを書いているのですが受信部、送信部をそれぞれ関数にしたらコンパイルエラーが出てしみました。
buf は文字が入るのでポインタを使ったほうが処理が速いのでポインタを使いたいのですがどのようにすればうまくできるでしょうか。

コード:

#include <stdio.h>
#include    <winsock2.h>
#pragma     once
#pragma     comment(lib,"ws2_32.lib")


bool setup();
bool network_read(char);
bool network_send();
bool end();

WSAData wsaData;
SOCKET  sock;
struct  sockaddr_in addr;

void main(){

	//受信データ
	char    buf[2048];    

	///設定
	setup();

	while(1){

		///データ受信
		network_read(*buf);
		///データ送信
		network_send();

	}
	///終了処理
	end();
}


bool network_send(){
    sendto(sock, "HELLO", 5, 0, (struct sockaddr *)&addr, sizeof(addr));
	return 0;
}

bool network_read(char *buf){
    memset(buf, 0, sizeof(buf));
    recv(sock, buf, sizeof(buf), 0);
	return 0;
}
bool setup(){
	
	WSAStartup(MAKEWORD(2,0), &wsaData);
    sock = socket(AF_INET, SOCK_DGRAM, 0);

    addr.sin_family = AF_INET;
    addr.sin_port = htons(12345);
    addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
return 0;
}
bool end(){
	
closesocket(sock);
    WSACleanup();
return 0;
}

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: UDP通信について

#2

投稿記事 by h2so5 » 12年前

27行目でポインタ型の引数に間接参照を渡しているのがコンパイルエラーの原因だと思います。

non
記事: 1097
登録日時: 14年前

Re: UDP通信について

#3

投稿記事 by non » 12年前

43行目sizeofも問題ありそうです。
non

こっこ

Re: UDP通信について

#4

投稿記事 by こっこ » 12年前

27行目だけ直しました。
43行目はよくわかりません。
下記のようなエラーが出ます。

エラー 1 error C2664: 'network_read' : 1 番目の引数を 'char [2048]' から 'char' に変換できません。(新しい機能 ; ヘルプを参照)

VC2012EX

コード:

#include <stdio.h>
#include    <winsock2.h>
#pragma     once
#pragma     comment(lib,"ws2_32.lib")
 
 
bool setup();
bool network_read(char);
bool network_send();
bool end();
 
WSAData wsaData;
SOCKET  sock;
struct  sockaddr_in addr;
 
void main(){
 
    //受信データ
    char    buf[2048];    
 
    ///設定
    setup();
 
    while(1){
 
        ///データ受信
        network_read(buf);
        ///データ送信
        network_send();
 
    }
    ///終了処理
    end();
}
 
 
bool network_send(){
    sendto(sock, "HELLO", 5, 0, (struct sockaddr *)&addr, sizeof(addr));
    return 0;
}
 
bool network_read(char *buf){
    memset(buf, 0, sizeof(buf));
    recv(sock, buf, sizeof(buf), 0);
    return 0;
}
bool setup(){
    
    WSAStartup(MAKEWORD(2,0), &wsaData);
    sock = socket(AF_INET, SOCK_DGRAM, 0);
 
    addr.sin_family = AF_INET;
    addr.sin_port = htons(12345);
    addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
return 0;
}
bool end(){
    
closesocket(sock);
    WSACleanup();
return 0;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: UDP通信について

#5

投稿記事 by softya(ソフト屋) » 12年前

まずエラーですが、
bool network_read(char);

bool network_read(char *buf){
で型が違うのが原因です。
この間違いで不安になるのは、ポインタの扱いや文字列の理解が不十分じゃないかと言うことです。

それとchar *bufは文字列バッファを渡せてもサイズは渡せませんので、sizeof(buf)はポインタのサイズとなり望んだ動作はしません。
サイズも引数にする必要があります。

コード:

bool network_read(char *buf){
    memset(buf, 0, sizeof(buf));
    recv(sock, buf, sizeof(buf), 0);
    return 0;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

こっこ

Re: UDP通信について

#6

投稿記事 by こっこ » 12年前

プロトタイプ宣言ですが、ポインタという型であることを忘れていました。
bool network_read(char *);

http://www7b.biglobe.ne.jp/~robe/cpphtm ... 01057.html
でポインタからサイズを取得することはできないことがよくわかりました。

これでいいでしょうか。

コード:

#include    <stdio.h>
#include    <winsock2.h>
#pragma     once
#pragma     comment(lib,"ws2_32.lib")
 
 
bool setup();
bool network_read(char *,int);
bool network_send();
bool end();
 
WSAData wsaData;
SOCKET  sock;
struct  sockaddr_in addr;
 
void main(){
 
    //受信データ
    char    buf[2048];    
 
    ///設定
    setup();
 
    while(1){
 
        ///データ受信
        network_read(buf,sizeof(buf));
        ///データ送信
        network_send();
 
    }
    ///終了処理
    end();
}
 
 
bool network_send(){
    sendto(sock, "HELLO", 5, 0, (struct sockaddr *)&addr, sizeof(addr));
    return 0;
}
 
bool network_read(char *buf ,int size){
    memset(buf, 0, size);
    recv(sock, buf, size, 0);
    return 0;
}
bool setup(){
    
    WSAStartup(MAKEWORD(2,0), &wsaData);
    sock = socket(AF_INET, SOCK_DGRAM, 0);
 
    addr.sin_family = AF_INET;
    addr.sin_port = htons(12345);
    addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
return 0;
}
bool end(){
    
closesocket(sock);
    WSACleanup();
return 0;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: UDP通信について

#7

投稿記事 by softya(ソフト屋) » 12年前

プロトタイプをまた間違っているので、エラーになると思いますよ。
コンパイルしてから投稿してくださいね。

ごめんなさい勘違いでした。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: UDP通信について

#8

投稿記事 by softya(ソフト屋) » 12年前

気を取り直して、不安なのは、recv(sock, buf, size, 0);で2048バイトぴっちり受信した場合に文字列終端がない場合がありえると言うことぐらいでしょうか。
あとは大丈夫だと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

こっこ

Re: UDP通信について

#9

投稿記事 by こっこ » 12年前

EOFがないこと自体は受信には何の問題もないが、そのあとの処理に注意するべきである。ということでいいでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: UDP通信について

#10

投稿記事 by softya(ソフト屋) » 12年前

EOFではなく文字列終端は0x00です。これはいくら注意しても誤動作するのでバッファギリギリまで受信するすのは避けるべきです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

こっこ

Re: UDP通信について

#11

投稿記事 by こっこ » 12年前

ありがとうございました。
最後に載せたソースコードが最終形です。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: UDP通信について

#12

投稿記事 by softya(ソフト屋) » 12年前

文字列を2048バイト受信すると、たぶん落ちるのでこれで良かったんでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

こっこ

Re: UDP通信について

#13

投稿記事 by こっこ » 12年前

??
受信には何も問題がなかったのでは。
やっぱり問題があるのですね。

http://chokuto.ifdef.jp/advanced/function/recv.html
で調べた結果切捨てされるだけなので問題ないと思っています。

勝手にプログラムが終了するわけではないと思っていますがこれは正しいでしょうか。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: UDP通信について

#14

投稿記事 by みけCAT » 12年前

このコードには、受信したデータを出力する部分は無いようです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: UDP通信について

#15

投稿記事 by softya(ソフト屋) » 12年前

No.8から書いている通り文字列終端の処理が考慮されていません。
この提示コードの範囲内では動作しますが、2048文字送ってしまった場合の動作は保証出来ません。
※ 現在のsendto()は5文字固定ですから。

>勝手にプログラムが終了するわけではないと思っていますがこれは正しいでしょうか。
たぶん、2048文字送ると異常終了するか、しないかもしれませんが2048文字以降が化けた文字列になると思います。
偶然無事な可能性もありますが常に無事な保証はできません。

[補足]
このコードの正常性は、受信した文字列の表示がない&5文字しか送っていないと言う限定条件の正常動作と言うことです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Poco
記事: 161
登録日時: 14年前

Re: UDP通信について

#16

投稿記事 by Poco » 12年前

まだ見ていることを祈りつつ。
UDPの場合、受信のためのAPIはrecv()ではなく、recvfrom()です。

こっこ

Re: UDP通信について

#17

投稿記事 by こっこ » 12年前

どうですか。
エラー処理をつけてみました。

コード:

#include    <stdio.h>
#include    <winsock2.h>
#pragma     once
#pragma     comment(lib,"ws2_32.lib")
 
 
bool setup();
bool network_read(char *,int);
bool network_send();
bool end();
 
WSAData wsaData;
SOCKET  sock;
struct  sockaddr_in addr;
 
void main(){
 
    //受信データ
    char    buf[2048];    
 
    ///設定
    setup();
 
    while(1){
 
        ///データ受信
        network_read(buf,sizeof(buf));
        ///データ送信
        network_send();
 
    }
    ///終了処理
    end();
}
 
 
bool network_send(){
    sendto(sock, "HELLO", 5, 0, (struct sockaddr *)&addr, sizeof(addr));
    return 0;
}
 
bool network_read(char *buf ,int size){
    memset(buf, 0, size);
    if(recv(sock, buf, size, 0) == -1){
      return 0;
    }
    return 1;
}
bool setup(){
    
    WSAStartup(MAKEWORD(2,0), &wsaData);
    sock = socket(AF_INET, SOCK_DGRAM, 0);
 
    addr.sin_family = AF_INET;
    addr.sin_port = htons(12345);
    addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
return 0;
}
bool end(){
    
closesocket(sock);
    WSACleanup();
return 0;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: UDP通信について

#18

投稿記事 by softya(ソフト屋) » 12年前

Pocoさんのが反映されてませんね。
それとrecv()のエラーにはならないので、自分で受信長を知らべてエラー処理なり、2047バイトに収まるようにするなり工夫してください。

[補足] あれ? Winsock2だとrecvform()じゃなくてrecv()でOKなのか? 調べてきます。
【補足追記】 bindしてないのでrecv()だと不可ですね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

こっこ

Re: UDP通信について

#19

投稿記事 by こっこ » 12年前

遅くなりました。
いろいろ付け加えてみました。
ここでまたいくつかの問題が発生しました。
受信を待つようなブロッキングモードにしておくとプログラムが止まってしまうのでノンブロッキングモードのしたのですがCPUの使用率が半端ないです。
解決方法としてはマルチスレッド等があるようですが全くわかりません。
どうしたらCPUの使用率を下げることができますか。

コード:

#include    <stdio.h>
#include    <winsock2.h>
#pragma     once
#pragma     comment(lib,"ws2_32.lib")
 
 
bool setup();
bool network_read(char *,int);
bool network_send();
bool end();
 
WSAData wsaData;
SOCKET  sock;
struct  sockaddr_in addr;
 
void main(){
 
    //受信データ
    char    buf[2048];    
 
    ///設定
    WSAStartup(MAKEWORD(2,0), &wsaData);
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(12345);
    addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    bind(sock, (struct sockaddr *)&addr, sizeof(addr));
    // ここで、ノンブロッキングに設定しています。
    u_long val=1;
    ioctlsocket(sock, FIONBIO, &val);
    
    while(1){
 
        ///データ受信
        network_read(buf,sizeof(buf));
        ///データ送信
        network_send();
 
    }
    ///終了処理
    closesocket(sock);
    WSACleanup();
}
 
 
bool network_send(){
    addr.sin_port = htons(宛先ポート);
    addr.sin_addr.S_un.S_addr = inet_addr("宛先IP");
    sendto(sock, "HELLO", 5, 0, (struct sockaddr *)&addr, sizeof(addr));
    return 0;
}
 
bool network_read(char *buf ,int size){
    memset(buf, 0, size);
    if(recv(sock, buf, size, 0) == -1){
      return 0;
    }
    return 1;
}


アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: UDP通信について

#20

投稿記事 by みけCAT » 12年前

while(1)のループ内にSleep(10);を入れるとCPU使用率は下がると思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

こっこ

Re: UDP通信について

#21

投稿記事 by こっこ » 12年前

ありがとうございます。
whileの一番下に入れても受信に失敗したらcontinueされるのでwhileの直後に入れることにしました。

コード:

#include    <stdio.h>
#include    <winsock2.h>
#pragma     once
#pragma     comment(lib,"ws2_32.lib")
 
 
bool setup();
bool network_read(char *,int);
bool network_send();
bool end();
 
WSAData wsaData;
SOCKET  sock;
struct  sockaddr_in addr;
 
void main(){
 
    //受信データ
    char    buf[2048];    
 
    ///設定
    WSAStartup(MAKEWORD(2,0), &wsaData);
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(12345);
    addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    bind(sock, (struct sockaddr *)&addr, sizeof(addr));
    // ここで、ノンブロッキングに設定しています。
    u_long val=1;
    ioctlsocket(sock, FIONBIO, &val);
    
    while(1){
 
        ///データ受信
        network_read(buf,sizeof(buf));
        ///データ送信
        network_send();
 
    }
    ///終了処理
    closesocket(sock);
    WSACleanup();
}
 
 
bool network_send(){
    addr.sin_port = htons(宛先ポート);
    addr.sin_addr.S_un.S_addr = inet_addr("宛先IP");
    sendto(sock, "HELLO", 5, 0, (struct sockaddr *)&addr, sizeof(addr));
    return 0;
}
 
bool network_read(char *buf ,int size){
    memset(buf, 0, size);
    if(recv(sock, buf, size, 0) == -1){
      return 0;
    }
    return 1;
}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: UDP通信について

#22

投稿記事 by みけCAT » 12年前

こっこ さんが書きました:whileの一番下に入れても受信に失敗したらcontinueされるのでwhileの直後に入れることにしました。
ごめんなさい。
提示されたコードには1箇所しかwhileが見えず、
そこではcontinueしている様子も無ければSleepしている様子も無いのですが、
どういう意味ですか?
オフトピック
こっこ さんが書きました:解決方法としてはマルチスレッド等があるようですが全くわかりません。
マルチスレッドにしたら余計にCPU使用率が上がるかもしれません。(OpenMP等)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

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