美好的一天,
我正在尝试发送"对象"通过插座。 结构如下所示:
typedef struct header_file
{
char chunk_id[4];
int chunk_size;
char format[4];
char subchunk1_id[4];
int subchunk1_size;
short int audio_format;
short int num_channels;
int sample_rate;
int byte_rate;
short int block_align;
short int bits_per_sample;
char subchunk2_id[4];
int subchunk2_size;
} header;
这是WAV声音文件的标题结构。 要读取该文件的那部分,我有:
FILE* infile = fopen("Sound.wav", "rb");
header *meta = (header*)malloc(sizeof(header));
if(infile){
fread(meta, 1, sizeof(header), infile);
}
到目前为止一切顺利,如果我尝试显示结构中包含的所有信息,完全没问题! 但是,我应该通过套接字发送它的部分:
n = write(socket_fd, meta, sizeof(header));
同样有效,但在服务器端,它只收到:
RIFF*_
前4个字符是结构数组chunk_id
中的字符,chunk size
是352042
,其中hexa给出0x00055F2A
我认为(至少我是这么认为)由于块大小中的零,服务器将其读作字符,并猜测0x00
的含义是什么?空值!字符串结束!
我该如何解决这个问题?
提前感谢您的帮助
完整的客户代码
void* stream_audio(void *arg);
typedef struct header_file
{
char chunk_id[4];
int chunk_size;
char format[4];
char subchunk1_id[4];
int subchunk1_size;
short int audio_format;
short int num_channels;
int sample_rate;
int byte_rate;
short int block_align;
short int bits_per_sample;
char samples_id[4];
int samples_size;
} header;
typedef struct header_file* header_p;
int KEEP_ALIVE = 1;
int PORT_NO = 5002;
char SERVER_IP[20] = "127.0.0.1";
pthread_t t_id;
int main(int argc, char * argv[]) {
int terr;
terr = pthread_create(&t_id, NULL, &stream_audio, NULL);
pthread_join(t_id, NULL);
}
void* stream_audio(void *arg){
FILE * infile = fopen("../files/man1_nb.wav","rb"); // Source WAV audio file
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
int count = 0; // For counting number of frames in wave file.
char buff16[2]; // short int used for 16 bit as input data format is 16 bit PCM audio
header_p meta = (header_p)malloc(sizeof(header)); // WAV file metadata fields
int nb;
portno = PORT_NO; // read port number from arguments
sockfd = socket(AF_INET, SOCK_STREAM, 0); // create socket
if (sockfd < 0) {
error("ERROR opening socket");
return ;
}
server = gethostbyname(SERVER_IP); // get host address from argument
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
return ;
}
// Create socket and connect to server
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
// send header WAV file trhough socket
if (infile){
fread(meta, 1, sizeof(header), infile);
meta->chunk_size = 0;
n = write(sockfd,meta,sizeof(meta));
if (n < 0)
error("ERROR writing to socket");
} else return;
int counter = 0;
while (!feof(infile))
{
bzero(buff16, sizeof(buff16));
nb = fread(buff16,1,1,infile); // Reading data in chunks of 16 bits (2 bytes)
n = write(sockfd,buff16,sizeof(buff16));
if(!KEEP_ALIVE){
fclose(infile);
close(sockfd);
return;
}
}
fclose(infile);
close(sockfd);
return;
}
完整的服务器代码
/* A simple server in the internet domain using TCP
The port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
char buffer[401];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,401);
char temper[100];
sprintf(temper, "/home/user/Documents/manif/bin/receiver%d.wav", portno);
FILE *receiver = fopen(temper,"wb+");
int empty = 0;
while(1){
memset(buffer,0,400);
n = read(newsockfd,buffer,400);
if (n < 0){
error("ERROR reading from socket");
break;
}
else if(n>0){
fwrite(buffer,1, n, receiver);
} else break;
printf("%s %d\n",buffer, n);
}
fclose(receiver);
close(sockfd);
return 0;
}
答案 0 :(得分:0)
您通过网络发送的内容是包含多个元素的struct
。但是,您尝试将您已阅读的内容打印为字符串,但它不是字符串。
您需要知道您收到的数据格式并以该格式阅读。
如果您只是为了调试而打印,那么循环读入的字节并将每个字节作为数字单独打印。您可能希望在发件人方面做同样的事情,以便能够比较它们。
此外,在客户端your use of feof
is incorrect。您应该检查fread
的返回值,看看您是否已达到文件结尾。这很可能是造成不匹配的原因。
答案 1 :(得分:0)
printf将打印ascii,非ascii(将在屏幕上显示行垃圾)字符,直到遇到\ 0,这就是为什么你在屏幕上只获得几个字节,因为它们旁边的字节必须是\ 0,如果你需要的话查看单独显示结构的每个成员所需的数据,或者只是在显示时将通过套接字接收的缓冲区转换为十六进制