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

标签 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);
  } 

 }

最佳答案

开始。

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

  2. 我建议您先阅读像这样的套接字编程教程 https://beej.us/guide/bgnet/

其次

我建议您使用 wireshark 之类的工具或任何其他正在运行的数据包分析器工具来调试您的问题。

最后你可以做类似下面的代码片段来尝试

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

    int rc = fcntl(newFd, F_GETFL,0);
    rc |= O_NONBLOCK;
    rc = fcntl(newFd, F_SETFL,rc);
    
  2. 为事件轮询套接字您可以使用诸如选择、轮询之类的东西
    相同的。这是 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
       }
    

关于c - 发送文件(客户端到服务器和服务器到客户端),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28001333/

相关文章:

python - 在 Python 中传递的 Unix 套接字凭证

c++ - 如何在 C/C++ 中实现条件?

c - C的未知模式提取

linux - 是否可以使用程序输出作为大括号扩展的值?

linux - 统计 Linux 命令的 IOPS

linux - 从文件中删除匹配词

c - 如何在不读取数据的情况下监听socket?

java - 尝试重用Java客户端套接字失败

c - C语言中,如何使用非当前文件的静态函数?

java - JNI 无法加载 native 库