c中的UDP:将接收到的数据保存为块时,会向文件中添加额外字符

c中的UDP:将接收到的数据保存为块时,会向文件中添加额外字符,c,file,file-io,udp,printf,C,File,File Io,Udp,Printf,我试图让一个简单的发送和接收UDP程序工作,但在保存接收到的数据时遇到了一些问题。据我所知,数据被正确地发送和接收,因为我已经在两端打印出来了。在我将数据写入文件之前(如果我只是打印出接收到的块),它没有任何额外的字符,所以我有点不知道它们来自哪里 当我将接收到的每个数据块追加到文件中时,它会在写入的每个数据块之后添加一个“^p^B^GÐ^”。例如,其中一个词块以“We,Thouse^P^B^GÐ^?”而不是“We,Thouse”结尾 感谢您的帮助,提前谢谢 更新: 我似乎已经让事情变得更好了

我试图让一个简单的发送和接收UDP程序工作,但在保存接收到的数据时遇到了一些问题。据我所知,数据被正确地发送和接收,因为我已经在两端打印出来了。在我将数据写入文件之前(如果我只是打印出接收到的块),它没有任何额外的字符,所以我有点不知道它们来自哪里

当我将接收到的每个数据块追加到文件中时,它会在写入的每个数据块之后添加一个“^p^B^GÐ^”。例如,其中一个词块以“We,Thouse^P^B^GÐ^?”而不是“We,Thouse”结尾

感谢您的帮助,提前谢谢


更新:

我似乎已经让事情变得更好了,我现在遇到了一个问题,用空字符替换每个块的第一个字符,例如:

“国会,1776年7月4日。”而不是“国会,1776年7月4日。”

它对接收到的每个区块的第一个字符执行此操作,我尝试了多个调试打印语句,但似乎无法找出问题所在

以下是我的接收和发送功能:

void receiveFile() {
int addr_len, bytesRead;
char recvData[BUFSIZE]; // Buffer to store received data
struct sockaddr_in server_addr, client_addr;

// Set up struct to receive data from our port and address
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero), 8);

addr_len = sizeof (struct sockaddr);

printf("\nWaiting for data on port %d\n", port);


//Keep reading data from the socket
while (1) {
    FILE *fp;
    fp=fopen("dummyfile.txt", "ab");

    memset(recvData, 0, BUFSIZE);
    bytesRead = recvfrom(sock, recvData, BUFSIZE, 0,
            (struct sockaddr *) &client_addr, &addr_len);
    int x;
    for(x = 0; x < bytesRead; x++) {
        fputc(recvData[x], fp);
    }

    // Print out who we're receiving from and what we're recieving
    printf("Receiving data from %s : %d\n", inet_ntoa(client_addr.sin_addr),
            ntohs(client_addr.sin_port));

    fclose(fp);
}}
void receiveFile(){
内部地址,字节读取;
char recvData[BUFSIZE];//用于存储接收数据的缓冲区
服务器地址、客户端地址中的结构sockaddr\u;
//设置struct以从端口和地址接收数据
服务器地址sin家庭=AF网络;
服务器地址sin\u端口=htons(端口);
server\u addr.sin\u addr.s\u addr=INADDR\u ANY;
bzero(&(服务器地址sin_zero),8);
addr_len=sizeof(结构sockaddr);
printf(“\n正在等待端口%d上的数据,\n”,端口);
//保持从套接字读取数据
而(1){
文件*fp;
fp=fopen(“dummyfile.txt”、“ab”);
memset(recvData,0,BUFSIZE);
bytesRead=recvfrom(sock、recvData、BUFSIZE、0、,
(结构sockaddr*)和客户机地址和地址;
int x;
对于(x=0;x
以下是发送功能:

void sendFile() {
// Announce who we're sending data to
if(DEBUG) { printf("\nSending %s to %s:%d\n", filename, address, port); }

// Open file
FILE * file = fopen(filename, "rb");
if (file == NULL) {
  perror("Invalid File\n");
  exit(1);
}

// Get size of the file
fseek(file, 0, SEEK_END);
int filesize = ftell(file);
rewind(file);

int curPos = 0;
int dataSize = 0;

while(curPos < filesize) {

    struct sockaddr_in server_addr; 
    struct hostent *recvr;

    char sendData[BUFSIZE]; // stores message to be sent
    memset(sendData, 0, BUFSIZE);

    int byte, i;
    for(i = 0; i < BUFSIZE; i++){
        if((filesize - curPos) > 0) {
            byte = fgetc(file);
            sendData[i] = byte;
            curPos++;
            dataSize++;
        }
        else { break; }
    }

    recvr = gethostbyname(address);
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr = *((struct in_addr *) recvr->h_addr);
    bzero(&(server_addr.sin_zero), 8);

    if(DEBUG) {
        char tempData[1201];
        strncpy(tempData, sendData, 1200);
        tempData[1201] ='\0';
        printf("%s\n\n\n\n\n", tempData);
    }

    sendto(sock, sendData, dataSize, 0,
            (struct sockaddr *) &server_addr, sizeof (struct sockaddr));
    dataSize = 0;
}

fclose(file);}
void sendFile(){
//宣布我们向谁发送数据
if(DEBUG){printf(“\n将%s发送到%s:%d\n”,文件名、地址、端口);}
//打开文件
FILE*FILE=fopen(文件名,“rb”);
if(file==NULL){
perror(“无效文件\n”);
出口(1);
}
//获取文件的大小
fseek(文件,0,SEEK_END);
int filesize=ftell(文件);
倒带(文件);
int curPos=0;
int-dataSize=0;
while(curPos0){
字节=fgetc(文件);
sendData[i]=字节;
curPos++;
dataSize++;
}
else{break;}
}
recvr=gethostbyname(地址);
服务器地址sin家庭=AF网络;
服务器地址sin\u端口=htons(端口);
服务器地址sin\u addr=*((地址中的结构)recvr->h\u addr);
bzero(&(服务器地址sin_zero),8);
如果(调试){
char tempData[1201];
strncpy(tempData,sendData,1200);
tempData[1201]='\0';
printf(“%s\n\n\n\n\n”,tempData);
}
sendto(sock、sendData、dataSize、0、,
(struct sockaddr*)和服务器地址,sizeof(struct sockaddr));
dataSize=0;
}
fclose(文件);}

将打印更改为:

fprintf(fp, "%.*s", bytesRead, recvData);
有一个保证,将不会空终止您的邮件;您必须自己传输空终止符


我不知道你还有什么问题。我有以下内容来完成背靠背工作的程序。我仔细检查了NUL保存的文件,没有问题

我把它们当作:

./recv & sleep 1; ./send; kill %1
记录c 标准c和标准h 事实上,除了我的代码之外,这根本不是标准。使用的函数具有以下声明:

extern void err_setarg0(const char *argv0);
extern void err_error(const char *format, ...) PRINTFLIKE(1,2) NORETURN();
extern void err_remark(const char *format, ...) PRINTFLIKE(1,2);
extern void err_syserr(const char *format, ...) PRINTFLIKE(1,2) NORETURN();
extern void err_usage(const char *usestr) NORETURN();

第一个记录程序名。第二个报告错误消息并退出;第三个报告消息并返回;第四个报告错误消息并添加来自“errno”和“strerror()”的错误信息(如果有);最后报告如何使用该程序-在本例中,程序不接受任何参数。完整的源代码(相当大)作为SQLCMD软件包的一部分在网站上提供,我也在网站上提交了其他各种程序。

Jonathan,他正在调用
memset()
在调用
recv()
之前将接收缓冲区归零;因此,缓冲区将被NUL终止。不一定,@Steve:被调用的函数不会写入超出传递的缓冲区边界的内容,但不会承诺在返回数据后不会留下额外的数据。我不确定这是否是问题所在——这就是为什么我的回答是一个问题。但我认为,确保接收者只处理告知其可用的数据是值得的。如果您发送的消息长度为BUFSIZE,那么接收缓冲区将不会被NUL终止,并且除非您将缓冲区的大小增加1,否则您将无法在接收端对其进行NUL终止。嗯,似乎出现了一个新问题,在实际服务器上运行时,它不会写入文件,它只会创建一个空文件。在本地主机上运行时,它会完美地发送文件。我已将目录中的权限设置为755,但它似乎仍然不起作用。@AnthonyJK:因为您的代码没有检查文件是否打开正常,所以您无法确定发生了什么。另外,您确定知道哪个目录是服务器的当前目录吗?您是否忘记了发送函数的文件名、地址和端口参数?或者它们真的是全局变量?发送循环不起作用
#include "posixver.h"
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "stderr.h"

#define bzero(b,len) (memset((b), '\0', (len)), (void)0)

enum { DEBUG = 1 };

static void sendFile(int sock, const char *filename, char *address, int port)
{
    // Announce who we're sending data to
    if (DEBUG)
        printf("\nSending %s to %s:%d\n", filename, address, port);

    // Open file
    FILE * file = fopen(filename, "rb");
    if (file == 0)
        err_syserr("Failed to open file %s", filename);

    // Get size of the file
    fseek(file, 0, SEEK_END);
    int filesize = ftell(file);
    rewind(file);

    int curPos = 0;
    int dataSize = 0;

    while (curPos < filesize)
    {
        struct sockaddr_in server_addr; 
        struct hostent *recvr;
        char sendData[BUFSIZ]; // stores message to be sent
        memset(sendData, 0, BUFSIZ);

        int byte, i;
        for (i = 0; i < BUFSIZ; i++){
            if ((filesize - curPos) > 0) {
                byte = fgetc(file);
                sendData[i] = byte;
                curPos++;
                dataSize++;
            }
            else
                break;
        }

        recvr = gethostbyname(address);
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(port);
        server_addr.sin_addr = *((struct in_addr *) recvr->h_addr_list[0]);
        bzero(&(server_addr.sin_zero), 8);

        if(DEBUG) {
            char tempData[1201];
            strncpy(tempData, sendData, 1200);
            tempData[1201] ='\0';
            printf("SEND:\n%s\n\n\n", tempData);
        }

        if (sendto(sock, sendData, dataSize, 0,
                (struct sockaddr *) &server_addr, sizeof (struct sockaddr)) < 0)
            err_syserr("Failed to send %d bytes\n", dataSize);
        dataSize = 0;
    }

    fclose(file);
}

int main(int argc, char **argv)
{
    int fd;

    err_setarg0(argv[0]);
    if (argc > 1)
        err_usage("");
    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
        err_syserr("Failed to open DGRAM socket");
    sendFile(fd, "/etc/passwd", "localhost", 5190);

    return(0);
}
#ifndef JLSS_ID_POSIXVER_H
#define JLSS_ID_POSIXVER_H

/*
** Include this file before including system headers.  By default, with
** C99 support from the compiler, it requests POSIX 2001 support.  With
** C89 support only, it requests POSIX 1997 support.  Override the
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE.
*/

/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */

#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600   /* SUS v3, POSIX 1003.1 2004 (POSIX 2001 + Corrigenda) */
#else
#define _XOPEN_SOURCE 500   /* SUS v2, POSIX 1003.1 1997 */
#endif /* __STDC_VERSION__ */
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */

#endif /* JLSS_ID_POSIXVER_H */
extern void err_setarg0(const char *argv0);
extern void err_error(const char *format, ...) PRINTFLIKE(1,2) NORETURN();
extern void err_remark(const char *format, ...) PRINTFLIKE(1,2);
extern void err_syserr(const char *format, ...) PRINTFLIKE(1,2) NORETURN();
extern void err_usage(const char *usestr) NORETURN();