简体   繁体   中英

How a client in Matlab can send binary data to server in C?

I want to send data from a client written in Matlab to a server written in C. When reading in the server, not all data is received in one read action and it is divided into two consecutive reads.

The Matlab code contains the code for a TCP server that receives some data, then does some processing and then writes (sends) the output of the processing over a TCP socket as a client to the server in C.

Here is the code for the client written in Matlab.

% A TCP server object defined for getting raw data and processing
% it. The object is called 'TCPServer'. It is not related to the 
% problem. 

% TCP client for sending the data to the C server
TCPClient = tcpip('192.168.1.2', 8080, 'NetworkRole', 'client');
set(TCPClient,'OutputBufferSize', 1464); 
% 1464 is total number of bytes of the struct to be sent
% to the C server.

set(TCPClient,'Timeout', 10);
fopen(TCPClient);

 while (1)
     while(1)       % Waits for incoming CSI data
         nBytes = get(TCPServer,'BytesAvailable');
         if nBytes >= bufferLen
             disp('Data received');
             break;
         end
     end

     data = fread(TCPServer,nBytes,'uint8');
     flushinput(TCPServer);

     % Does some processing and generate 'spec' and 'doas'
     % arrays to be sent to the C server

     message = [typecast(spec, 'uint8') typecast(doas, 'uint8')];
     fwrite(TCPClient, message); 
 end

Here is the code written in C for the server receiving the data from the client in Matlab.

#define SA struct sockaddr

struct doa_struct {
    double spec[181], doa[2];
};

// Function that reads received data
void func(int sockfd) 
{ 
    struct doa_struct *doa_data;
    unsigned char buff[1464];
    int num_bytes;
    // infinite loop receiving data
    for (;;) { 
        bzero(buff, 1464); 

        // read the data from client and copy it in buffer 
        num_bytes = read(sockfd, buff, 1464);
        // Get the buffer which contains the client contents 
        doa_data = (struct doa_struct *) buff; 
        printf("doa: %f\t%f\t%d\n", doa_data->doa[0], doa_data->doa[1], num_bytes);
    }
} 

// Driver function 
int main()
{ 
    int sockfd, connfd, len;
    struct sockaddr_in servaddr, cli; 

    // socket create and verification
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd == -1) { 
        printf("socket creation failed...\n"); 
        exit(0); 
    } 
    else
        printf("Socket successfully created..\n"); 
    bzero(&servaddr, sizeof(servaddr)); 

    // assign IP, PORT 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(8080); 

    // Binding newly created socket to given IP and verification
    if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
        printf("socket bind failed...\n");
        exit(0);
    }
    else
        printf("Socket successfully binded..\n");

    // Now server is ready to listen and verification
    if ((listen(sockfd, 5)) != 0) {
        printf("Listen failed...\n");
        exit(0);
    }
    else
        printf("Server listening..\n");
    len = sizeof(cli);

    // Accept the data packet from client and verification
    connfd = accept(sockfd, (SA*)&cli, &len);
    if (connfd < 0) {
        printf("server acccept failed...\n");
        exit(0); 
    } 
    else
        printf("server acccept the client...\n");

    // Function for chatting between client and server
    func(connfd);

    // After chatting close the socket
    close(sockfd); 
} 

I receive the following result on the server.

doa: 0.000000   0.000000    1408
doa: 0.000000   0.000000    56

Each line printed has three values. The first two are the received data that should not be zero. The last number is the number of bytes received by read() function in the server. The sum of bytes received by the server in the two lines (two read() operations) is 1464 which is the number of bytes sent by the client in one fwrite() operation.

The correct output would be one line like the following:

doa: 25.000000  45.000000   1464

Two non-zero data values received by a transfer of 1464 bytes. I have also checked the client code. The client sends (writes) 1464 bytes by fwrite() operation in Matlab.

It's completely normal for a read() call to only return some of the data you're expecting. This happens because at a low level, the network stack breaks the overall data stream up into multiple fixed-size packets for transmission over the wire. From the read(2) man page:

RETURN VALUE ... It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal.

When receiving network data, you'll need to keep calling read() until you've received the expected number of bytes. For example, something like this (untested code):

void func(int sockfd) 
{ 
    struct doa_struct *doa_data;
    int expected_bytes = 1464;
    unsigned char buff[expected_bytes];
    int num_bytes;

    // Read a message
    bzero(buff, 1464);
    int bytes_read = 0;
    while (bytes_read < expected_bytes) {

        // read data into buff until we've read all the expected bytes
        // NOTE: if the Matlab side sends a malformed message, this could
        // hang in this loop forever...for real-world use, you'd need to
        // account for those types of scenarios.
        num_bytes = read(sockfd, buff + bytes_read, expected_bytes - bytes_read);
        if (num_bytes <= 0) {
            // handle error cases...
            return;
        }
        bytes_read += num_bytes;
    }

    // Get the buffer which contains the client contents 
    doa_data = (struct doa_struct *) buff; 
    printf("doa: %f\t%f\t%d\n", doa_data->doa[0], doa_data->doa[1], num_bytes);
}

As for why your output is printing 0's instead of the expected values: it may be because of your printf format specifier. Your compiler may require "%lf" to print doubles, rather than "%f". Traditionally, the "%lf" was required for doubles, which are 64-bit values rather than the 32-bit float values. However, C99 and later compilers can blur this line -- see this related stack overflow question .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM