发送文件(客户端到服务器和服务器到客户端)

时间:2015-01-17 16:02:07

标签: c linux sockets

我有client.c和server.c,我试图将文件从客户端发送到服务器,从服务器发送到客户端...... 该文件由服务器接收,但是当服务器发送文件时,客户端停止或不接收该文件, sendFile()函数:

void sendfile(int fd,char* filename)
{
    char buff[0x1000]; 
    FILE *file = fopen(filename, "rb"); 
    if (!file)
    {
        printf("Can't open file for reading"); 
        return;
    }
    while (!feof(file)) 
    { 
        int rval = fread(buff, 1, sizeof(buff), file); 
        if (rval < 1)
        {
            printf("Can't read from file\n");
            fclose(file);
            return;
        }

        int off = 0;
        do
        {
            int sent = send(fd, &buff[off], rval - off, 0);
            printf("Sending ...\n");
            if (sent < 1)
            {
                printf("Can't write to socket");
                fclose(file);
                return;
            }
            printf("[SendFile]Fisierul a fost trimis!\n");
            off += sent;
        }
        while (off < rval);
    } 
 fclose(file);
} 

getFile():

void getFile(int fd,char* filename)
 {
    int rval; 
    char buff[0x1000]; 
    FILE *file = fopen(filename, "w+"); 
    if (!file)
    {
        printf("Can't open file for writing");
        return;
    }

    do
    {
        rval = recv(fd, buff, sizeof(buff), 0);
        if (rval < 0)
        {
            printf("Can't read from socket");
            fclose(file);
            return;
        }

        if (rval == 0)
            break;

        int off = 0;
        do
        {
            int written = fwrite(&buff[off], 1, rval - off, file);
        printf("[server]Writing %d bytes\n",written);
            if (written < 1)
            {
                printf("Can't write to file");
                fclose(file);
                return;
            }

            off += written;
        }
        while (off < rval);
    printf("[server]File received!\n"); 
    }  
    while(1);
    fclose(file); 
 }

客户端main():

int main (int argc, char *argv[])
{
  int sd;
  struct sockaddr_in server;

  if (argc != 2)
    {
      printf ("[client] Sintaxa: %s <filename>\n", argv[0]);
      return -1;
    }

  if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
    {
      perror ("[client] Eroare la socket().\n");
      return errno;
    }

  server.sin_family = AF_INET;
  server.sin_addr.s_addr = inet_addr("127.0.0.1");
  server.sin_port = htons (port);

  if (connect (sd, (struct sockaddr *) &server,sizeof (struct sockaddr)) == -1)
    {
      perror ("[client]Eroare la connect().\n");
      return errno;
    }
    sendfile(sd,"test.cpp");
    printf("File sent\n");
    getFile(sd,"server.c");
    close (sd);
}

来自server.c的循环

while (1)
    {
      int client;
      int length = sizeof (from);

      printf ("[server]Asteptam la portul %d...\n",port);
      fflush (stdout);

      client = accept (sd, (struct sockaddr *) &from, &length);

      if (client < 0)
      {
      perror ("[server]Eroare la accept().\n");
      continue;
      }

    if((pid=fork()) == 0 )
    {

    getFile(client,"test.cpp");
        sendfile(client,"server.c");
        printf("File sent\n");
    close(client);
  } 

 }

2 个答案:

答案 0 :(得分:3)

开头。

  1. accept(),connect(),recv()..所有都是阻塞调用所以理论上你的程序可以在这些调用中的任何地方被阻塞,直到你使用非阻塞套接字。从程序看起来你正在使用阻塞套接字

  2. 我建议你先读一个好的套接字编程教程 https://beej.us/guide/bgnet/

  3. 其次

    我建议您使用wireshark或任何其他数据包分析工具等工具来调试您的问题。

    最后,您可以执行类似以下代码段的操作

    1. 使用fnctl API调用将套接字设置为非阻塞模式。

      int rc = fcntl(newFd, F_GETFL,0);
      rc |= O_NONBLOCK;
      rc = fcntl(newFd, F_SETFL,rc);
      
    2. 轮询套接字以查找事件您可以使用类似select,poll之类的内容 相同。这是Beej教程中选择的一个很好的例子。 的 https://beej.us/guide/bgnet/html/multi/selectman.html

    3. 正确处理错误。非阻塞套接字可以返回EAGAIN或EWOULDBLOCK错误,必须正确处理。该错误意味着在查找事件时套接字不可读或不可写,请重试。有点像。

        rval = recv(fd, buff, sizeof(buff), 0);
        if (rval < 0)
        {
             if((errno == EWOULDBLOCK)||(errno ==EAGAIN))
             {
                 continue;
             }
             else
                 //cleanup
         }
      

答案 1 :(得分:0)

tre问题是来自getFile的do { ... } while(1); ...所以我删除了循环...