Matlab 中的客户端如何将二进制数据发送到 C 中的服务器?
How a client in Matlab can send binary data to server in C?
我想从一个用Matlab写的客户端发送数据到一个用C写的服务器。当在服务器中读取时,并不是所有的数据都在一次读取操作中被接收到,它被分成两次连续的读取。
Matlab 代码包含 TCP 服务器的代码,该服务器接收一些数据,然后进行一些处理,然后通过 TCP 套接字将处理的输出作为客户端写入(发送)到 C 中的服务器。
这里是用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
这里是用C语言编写的代码,用于在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);
}
我在服务器上收到以下结果。
doa: 0.000000 0.000000 1408
doa: 0.000000 0.000000 56
打印的每一行都有三个值。前两个是接收到的不应该为零的数据。最后一个数字是服务器中 read()
函数接收的字节数。服务器在两行(两次 read()
操作)中接收到的字节总和为 1464
,这是客户端在一次 fwrite()
操作中发送的字节数。
正确的输出应该是一行,如下所示:
doa: 25.000000 45.000000 1464
通过 1464
字节的传输接收到两个非零数据值。我还检查了客户端代码。客户端在Matlab中通过fwrite()
操作发送(写入)1464
字节。
read() 调用仅 return 您期望的一些数据是完全正常的。发生这种情况是因为在低级别,网络堆栈将整个数据流分解为多个固定大小的数据包,以便通过线路传输。来自 read(2) 手册页:
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.
接收网络数据时,您需要不断调用 read() 直到接收到预期的字节数。例如,像这样的东西(未经测试的代码):
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);
}
至于为什么您的输出打印的是 0 而不是预期值:这可能是因为您的 printf 格式说明符。你的编译器可能需要 "%lf" 来打印双打,而不是 "%f"。传统上,双精度值需要“%lf”,这是 64 位值而不是 32 位浮点值。但是,C99 和更高版本的编译器可以模糊这条线——参见 this related stack overflow question.
我想从一个用Matlab写的客户端发送数据到一个用C写的服务器。当在服务器中读取时,并不是所有的数据都在一次读取操作中被接收到,它被分成两次连续的读取。
Matlab 代码包含 TCP 服务器的代码,该服务器接收一些数据,然后进行一些处理,然后通过 TCP 套接字将处理的输出作为客户端写入(发送)到 C 中的服务器。
这里是用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
这里是用C语言编写的代码,用于在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);
}
我在服务器上收到以下结果。
doa: 0.000000 0.000000 1408
doa: 0.000000 0.000000 56
打印的每一行都有三个值。前两个是接收到的不应该为零的数据。最后一个数字是服务器中 read()
函数接收的字节数。服务器在两行(两次 read()
操作)中接收到的字节总和为 1464
,这是客户端在一次 fwrite()
操作中发送的字节数。
正确的输出应该是一行,如下所示:
doa: 25.000000 45.000000 1464
通过 1464
字节的传输接收到两个非零数据值。我还检查了客户端代码。客户端在Matlab中通过fwrite()
操作发送(写入)1464
字节。
read() 调用仅 return 您期望的一些数据是完全正常的。发生这种情况是因为在低级别,网络堆栈将整个数据流分解为多个固定大小的数据包,以便通过线路传输。来自 read(2) 手册页:
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.
接收网络数据时,您需要不断调用 read() 直到接收到预期的字节数。例如,像这样的东西(未经测试的代码):
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);
}
至于为什么您的输出打印的是 0 而不是预期值:这可能是因为您的 printf 格式说明符。你的编译器可能需要 "%lf" 来打印双打,而不是 "%f"。传统上,双精度值需要“%lf”,这是 64 位值而不是 32 位浮点值。但是,C99 和更高版本的编译器可以模糊这条线——参见 this related stack overflow question.