使用套接字处理二进制文件的概率

Prob with binary files using sockets

这不是全部代码。

这对文本文件等普通文件工作正常,但对 tar.gz 和二进制文件传输不起作用,请帮助我。

以及如何使用套接字发送内存块。

server.c

void main()
{
int sockfd, new_fd;  // listen on sock_fd, new connection on new_fd
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char buf[16384];
char remotefile[MAXDATASIZE];
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
    perror("socket");
    exit(1);
}

if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) 
{
    perror("setsockopt");
    exit(1);
}

my_addr.sin_family = AF_INET;        // host byte order
my_addr.sin_port = htons(MYPORT);    // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(my_addr.sin_zero, '[=10=]', sizeof my_addr.sin_zero);

printf("call binding\n");
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) == -1) 
{
    perror("bind");
    exit(1);
}

if (listen(sockfd, BACKLOG) == -1) 
{
    perror("listen");
    exit(1);
}

sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) 
{
    perror("sigaction");
    exit(1);
}

while(1)
{  // main accept() loop
    sin_size = sizeof their_addr;
    if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) 
    {
        perror("accept");
        exit(1);
        continue;
    }
    printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
    if (!fork()) 
    { // this is the child process
if ((byt=recv(new_fd, remotefile, MAXDATASIZE-1, 0)) == -1) 
            {
                perror("server recv");
                exit(1);
            }
        int serverfile_fd;
        size_t result;
        printf("\nremotefile in val1 is %s\n",remotefile);

        if((serverfile_fd = open(remotefile,O_RDONLY)) < 0)
        {
            printf("error at remotefile\n");
            exit(1);
        }

        else
         {  
            read(serverfile_fd, &buf[0], sizeof(buf));
         }
        //printf("file is\n%s", buf);
        /* 3. sending  buf in val 0*/
        if (send(new_fd, buf, 16384, 0) == -1)
            perror("send");
        close(new_fd);
        exit(0);
    }

client.c

int remote_to_local(const  char *remotehost,const  char *remotefile,const  char *localfile)
{

int sockfd, numbytes,i = 0,j = 0;  
char buf[16384];
struct hostent *he;
struct sockaddr_in s_addr; // connector's address information 
printf("\n");
printf("Remotehost is %s\n", remotehost);
if ((he=gethostbyname(remotehost)) == NULL) 
{  // get the host info 
    perror("gethostbyname");
    exit(1);
}

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
{
    perror("socket");
    exit(1);
}

s_addr.sin_family = AF_INET;    // host byte order 
s_addr.sin_port = htons(PORT);  // short, network byte order 
s_addr.sin_addr = *((struct in_addr *)he->h_addr);
//inet_aton(he->h_addr, &s_addr.sin_addr);
memset(s_addr.sin_zero, '[=11=]', sizeof s_addr.sin_zero);

if (connect(sockfd, (struct sockaddr *)&s_addr, sizeof s_addr) == -1) 
{
    perror("connect");
    exit(1);
}

//send(sockfd, remotefile, MAXDATASIZE-1, 0);
val[0] = 1;
printf("Val 0 is %d\n", val[0]);
printf("Val 1 is %d\n", val[1]);
        /*1 sending val in r to l*/
if (send(sockfd, val, MAXDATASIZE-1, 0) == -1)
            perror("send");

printf("remotefile is %s\n",remotefile);

/* 2 sending remotefile in r to l*/
if (send(sockfd, remotefile, MAXDATASIZE-1, 0) == -1)
            perror("send");
/* 3. recieve buf in r to l */  
if ((numbytes=recv(sockfd, buf, 16384, 0)) == -1) 
{
    perror("recv");
    exit(1);
}

buf[numbytes] = '[=11=]';

//printf("Received: \n%s",buf);


int clientfile_fd;
printf("Local file is %s\n",localfile);
if((clientfile_fd = open(localfile,O_CREAT|O_WRONLY,0777)) < 0)
    {
       printf("error at remotefile\n");
        exit(1);
    }
   else
   {    
        //read(clientfile_fd, &buf[0], sizeof(buf));
         int  result = strlen(buf); 
         //printf("Result size is %d\n",result);
         open(localfile,O_TRUNC);
         write(clientfile_fd, &buf[0], result);
   }

close(sockfd);


return 0;
  }

检查你所有的代码和fix/change你的所有地方:

  • 没有正确处理系统调用返回的结果,例如 接收()。如果返回正值,则该值是唯一安全的 找出有多少数据已读入缓冲区的方法。
  • 去掉所有的 strlen(), printf("%s...) 等 无用,(二进制数据可能包含空值,因此操作将 尽早完成)或危险的(二进制数据根本不包含空值 所以调用是 UB)。

以下接收文件的逻辑已经比你的好很多了。但是您的代码存在的问题远不止这些:

 FILE *received_file;
 received_file = fopen(FILENAME, "w");
 ...
 //copy logic, copies data received from the socket into the file as is.
 while (((len = recv(client_socket, buffer, BUFSIZ, 0)) > 0))
    {
            fwrite(buffer, sizeof(char), len, received_file);
    }
    fclose(received_file);
   close(client_socket);

receive 会持续调用,直到您收到 0 或负数,如果您收到 0 则意味着您需要关闭套接字,因为传输已完成并且对等方也已关闭其连接端。 文件句柄应在接受后立即创建。

最重要的是,您的代码需要彻底修改,因为它对于它应该做的事情来说太长了,而且它基于完全错误的假设。在尝试这样的事情之前先阅读网络编程。套接字编程是个高级话题,理解不当就会失败