2016-07-21 10 views
4

プログラミングでは初心者です。ソケットC/C++でfloat値を送信

サーバー:

#include <stdlib.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <string.h> 
#include <unistd.h> 

#define MAXLINE 4096 /*max text line length*/ 
#define SERV_PORT 3000 /*port*/ 
#define LISTENQ 8 /*maximum number of client connections */ 

int main (int argc, char **argv) 
{ 
    int listenfd, connfd, n; 
    socklen_t clilen; 
    char buf[MAXLINE]; 
    struct sockaddr_in cliaddr, servaddr; 

    //creation of the socket 
    listenfd = socket (AF_INET, SOCK_STREAM, 0); 

    //preparation of the socket address 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    servaddr.sin_port = htons(SERV_PORT); 

    bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); 

    listen(listenfd, LISTENQ); 

    printf("%s\n","Server running...waiting for connections."); 

    for (; ;) { 

     clilen = sizeof(cliaddr); 
     connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen); 
     printf("%s\n","Received request..."); 

     while ((n = recv(connfd, buf, MAXLINE,0)) > 0) { 
      printf("%s","String received from and resent to the client:"); 
      puts(buf); 
      send(connfd, buf, n, 0); 
     } 

     if (n < 0) { 
      perror("Read error"); 
      exit(1); 
     } 
     close(connfd); 

    } 
    //close listening socket 
    close(listenfd); 

} 

クライアント:

私は、インターネット上でこのサンプルコードを発見し、それが正常に動作させるために管理C.内の別の1にC++でのプログラムからいくつかのfloat値を送信する必要があります
#include <stdlib.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <string.h> 
#include <arpa/inet.h> 


#define MAXLINE 4096 /*max text line length*/ 
#define SERV_PORT 3000 /*port*/ 

int 
main(int argc, char **argv) 
{ 
    int sockfd; 
    struct sockaddr_in servaddr; 
    char sendline[MAXLINE], recvline[MAXLINE]; 

    //basic check of the arguments 
    //additional checks can be inserted 
    if (argc !=2) { 
     perror("Usage: TCPClient <IP address of the server"); 
     exit(1); 
    } 

    //Create a socket for the client 
    //If sockfd<0 there was an error in the creation of the socket 
    if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) <0) { 
     perror("Problem in creating the socket"); 
     exit(2); 
    } 

    //Creation of the socket 
    memset(&servaddr, 0, sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr= inet_addr(argv[1]); 
    servaddr.sin_port = htons(SERV_PORT); //convert to big-endian order 

    //Connection of the client to the socket 
    if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))<0) { 
     perror("Problem in connecting to the server"); 
     exit(3); 
    } 

    while (fgets(sendline, MAXLINE, stdin) != NULL) { 

     send(sockfd, sendline, strlen(sendline), 0); 

     if (recv(sockfd, recvline, MAXLINE,0) == 0){ 
      //error: server terminated prematurely 
      perror("The server terminated prematurely"); 
      exit(4); 
     } 
     printf("%s", "String received from the server: "); 
     fputs(recvline, stdout); 
    } 

    exit(0); 
} 

フロート値をサーバーに送信して戻すために追加する必要があるのは何ですか?マシンはx86ベースで、Debian 6がインストールされているマシンとLinux Mintがインストールされているマシンです。私は両方の方法(DebianとクライアントとLinuxのミントをサーバーとDebianをサーバーとLinuxのミントをクライアントと)で試してみましたが、うまくいきました。 I m thinking about making some casting between a char value and float... Itこれは可能ですか?キャストせずに送る方法はありますか?私はchar値が必要ではなく、いくつかのfloat値しか必要としません。 あなたの助けをいただきありがとうございます!

編集:snprintfとsscanfを試しましたが、正しく動作しないため何か間違っています。ここではクライアントとサーバーは、現時点では、次のとおりです。

クライアント:

#include <stdlib.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <string.h> 
#include <arpa/inet.h> 


#define MAXLINE 4096 /*max text line length*/ 
#define SERV_PORT 3000 /*port*/ 

int 
main(int argc, char **argv) 
{ 
int sockfd; 
struct sockaddr_in servaddr; 
char sendline[MAXLINE], recvline[MAXLINE], buffer [256]; 
//Añadidas por mi// 
float a, b, c; 
a = 0; 
b = 0; 
c = 0; 
c = a + b; 

    printf("\nPrimer numero: "); 
    scanf("%f", &a); 
    printf ("\nSegundo numero: "); 
    scanf ("%f", &b); 

sprintf(buffer, "%f", sizeof c, c); 


unsigned char len = strlen(buffer); 

//basic check of the arguments 
//additional checks can be inserted 
if (argc !=2) { 
    perror("Usage: TCPClient <IP address of the server"); 
    exit(1); 
} 

//Create a socket for the client 
//If sockfd<0 there was an error in the creation of the socket 
if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) <0) { 
    perror("Problem in creating the socket"); 
    exit(2); 
} 

//Creation of the socket 
memset(&servaddr, 0, sizeof(servaddr)); 
servaddr.sin_family = AF_INET; 
servaddr.sin_addr.s_addr= inet_addr(argv[1]); 
servaddr.sin_port = htons(SERV_PORT); //convert to big-endian order 

//Connection of the client to the socket 
if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr))<0) { 
    perror("Problem in connecting to the server"); 
    exit(3); 
} 

while (fgets(sendline, MAXLINE, stdin) != NULL) { 

    send(sockfd, sendline, strlen(sendline), 0); 
    send(sockfd, &len, sizeof len, 0); 
    send (sockfd, buffer, sizeof buffer, 0); 

    if (recv(sockfd, recvline, MAXLINE,0) == 0){ 
    //error: server terminated prematurely 
    perror("The server terminated prematurely"); 
    exit(4); 
    } 
    printf("%s", "String received from the server: "); 
    fputs(recvline, stdout); 
} 

exit(0); 
} 

サーバー:

#include <stdlib.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <string.h> 
#include <unistd.h> 

#define MAXLINE 4096 /*max text line length*/ 
#define SERV_PORT 3000 /*port*/ 
#define LISTENQ 8 /*maximum number of client connections */ 

int main (int argc, char **argv) 
{ 
float c; 
int listenfd, connfd, n; 
socklen_t clilen; 
char buf[MAXLINE], buf256[256], buffer[256]; 
unsigned char len = strlen(buffer); 
struct sockaddr_in cliaddr, servaddr; 

//creation of the socket 
listenfd = socket (AF_INET, SOCK_STREAM, 0); 

//preparation of the socket address 
servaddr.sin_family = AF_INET; 
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
servaddr.sin_port = htons(SERV_PORT); 

bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); 

listen(listenfd, LISTENQ); 

printf("%s\n","Server running...waiting for connections."); 

for (; ;) { 

    clilen = sizeof(cliaddr); 
    connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen); 
    printf("%s\n","Received request..."); 

    while ((n = recv(connfd, buf, MAXLINE,0)) > 0) { 
    printf("%s","String received from and resent to the client:"); 
    puts(buf); 


    recv(connfd, &len, sizeof len, 0); 
    recv(connfd, buf256, len, 0); 
    recv(connfd, buffer, 256, 0); 
    buf256[len] = 0; 
    sscanf(buffer, "%f", &c); 
    puts(buffer); 
    printf ("\n%f", &c); 
    send(connfd, buf, n, 0); 
    } 

if (n < 0) { 
    perror("Read error"); 
    exit(1); 
} 
close(connfd); 

} 
//close listening socket 
close(listenfd); 
} 

プログラムは奇妙な作品、それが何を示していないdoesntの時々0.0000Eのような値を示していますか。私はさまざまな浮動小数点値を送信する必要があるので、このプログラムは浮動小数点値を1つだけ送る方法の例です。私のプログラムのどこにエラーがあるのか​​誰にでも見えますか?ありがとう!

+6

send/recv関数を使用するときは、文字配列ではなくバッファを考慮する必要があります。 float変数(sizoef(float))のサイズとともに、/ recvを送るためにあなたのfloat変数のアドレスを渡します。プログラミングでは初心者だと言っているので、ソケットを使ってバイナリデータを送受信すると、バイトオーダーや個々の値の幅などの微妙な違いがあることを指摘しておきます。あなたの場合、あなたは自分自身をx86マシンに制限しますが、それはうまくいくはずですが、クライアント/サーバーソフトウェアを開発するときはこれを想定しないことをお勧めします。 –

+4

'float'を' sprintf'で文字列に変換し、文字列から 'sscanf'で' float'に変換し直します。エンディアン、アライメント、エンコーディング(ieee754)、サイズ(通常は4バイト)、... – user3386109

+4

@ user3386109:注意:浮動小数点演算を往復させたい場合、小数点値を使用してポイント値を取得するには、十分な数字( 'float'の場合はIIRC 9)で' fprintf() 'を確認する必要があります。おそらく、 ''%a "'を持つ16進浮動小数点として 'fprintf()'を使う方が良いでしょう。 – EOF

答えて

1

コードは、floatをバイナリ表現で送信できます。これはよくマッチしたシステムではうまくいくかもしれませんし、そうでなければfloat表現やエンディアンの違いによって失敗するかもしれません。 @clarasoft-it

float x = ...; 

// send 
send(sockfd, &x, sizeof x, 0); 

// receive 
recv(connfd, &x, sizeof x, 0); 

代替コードはsufficient digitsで印刷文字列表現を使用してfloat送信することができます。これはより移植性があります。エンディアンに問題はありません。文字列の長さ情報を伝える必要があります。 @user3386109@EOF

浮動小数点形式が両端で異なる場合、範囲と精度の問題には追加の処理が必要になる可能性があります。これは使用する方法に関係なく問題となります。

#include <float.h> 
#define FLT_EXPO_SIZE 5 

// send 
// create a buffer large enough 
//  - d .  ddddd     e -  expo  \0 
char buf[1 + 1 + 1 + (FLT_DECIMAL_DIG - 1) + 1 + 1 + FLT_EXPO_SIZE + 1]; 
// print the value to enough digits to distinguish x from all other float 
unsigned char len = sprintf(buf, "%.*e", FLT_DECIMAL_DIG - 1, x); 
send(sockfd, &len, sizeof len, 0); 
send(sockfd, buf, sizeof buf, 0); 

// receive 
char buf256[256]; 
recv(connfd, &len, sizeof len, 0); 
recv(connfd, buf256, len, 0); 
buf256[len] = 0; 
sscanf(buf256, "%f", &x);    // add sscanf() check 

注:

  1. 他のコードはより良いFLT_MIN_EXPFLT_MAX_EXP多分FLT_TRUE_MINに基づいて保守的な5.サムシングよりFLT_EXPO_SIZEを定義するために使用することができます。

  2. sprintf("%a", x);を16進表現に使用できます。その場合はTBDのバッファサイズが必要です。引き続き使用できますsscanf(buf, "%f", &x)

  3. snprintf()を使用できます。

  4. 簡潔にするため、さまざまなエラーチェックが省略されています。

+0

回答ありがとうございました。私はsprintfとsscanfメソッドを試してみます。私は試してみると私の進歩を掲載します! – Joaquin

+0

まだ浮動小数点値の送信に問題がありますが、私のプログラムは正しく動作しません。私はそれを修正した瞬間にコードに質問を追加しましたが、正しく動作しません。 – Joaquin

+2

'strlen'呼び出しは不要です。これは' snprintf'が長さを返しますが無視されるためです。 –

関連する問題