【问题标题】:null character within a string in CC中字符串中的空字符
【发布时间】:2017-09-26 13:46:57
【问题描述】:

大家好,

我正在尝试通过套接字发送“对象”。 结构如下:

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 size352042,在 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; 
}

【问题讨论】:

标签: c string sockets struct null


【解决方案1】:

您通过网络发送的是包含多个元素的struct。但是,您正在尝试将您读到的内容打印为字符串,但它不是字符串。

您需要知道您收到的数据的格式并以该格式阅读。

如果您只是出于调试目的而打印,则循环读取读入的字节并将每个字节单独打印为数字。您可能希望在发件人端执行相同操作以便能够比较它们。

另外,在客户端,your use of feof is incorrect。相反,您应该检查 fread 的返回值以查看您是否已到达文件末尾。这很可能是导致不匹配的原因。

【讨论】:

  • 实际上我尝试打印只是为了看看可能是什么问题。我实际上想将收到的任何内容保存到 WAV 文件中,而不是读取。只需读写二进制文件,仅此而已。但是服务器端创建的文件和客户端创建的文件不一样...
【解决方案2】:

printf 将打印 ascii,非 ascii(将在屏幕上看起来是垃圾)字符,直到遇到 \0,这就是为什么你在屏幕上只看到几个字节,因为如果你需要,它们旁边的字节必须是 \0查看您需要单独显示结构的每个成员的数据,或者只是在显示时将通过套接字接收的缓冲区转换为十六进制

【讨论】:

    猜你喜欢
    • 2020-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-21
    • 1970-01-01
    • 1970-01-01
    • 2014-04-30
    相关资源
    最近更新 更多