3

所以我正在玩弄端口和客户端/服务器通信的想法。

我有一个 server.c 程序,它可以打开一个端口,打开一个监听描述符,并在接收到连接后,派生一个孩子来处理与连接客户端的通信。我有一个接受 5 个命令行参数的 client.c 程序。基本上前 3 个参数是发送到服务器的练习字符串,第 4 个是主机名,第 5 个是端口号。

到目前为止,将这两者连接起来效果很好,但是,当客户端尝试将 3 个不同的字符串(argv[1]、argv[2] 和 argv[3])写入 server.c 时,server.c 似乎只是能够读取第一个然后它似乎被卡住并且即使客户端将完成将所有字符串写入通信文件描述符也不会继续进行其他读取。我被困了 4 个多小时,试图找出一个简单的练习程序来更好地学习服务器和客户端。我不想再迷路了,所以我希望有人能给我任何关于如何处理这个问题或我做错了什么的建议。

客户端.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "uici.h"
#include "func.h"


int main(int argc, char *argv[]){
  int fd;
  u_port_t portnum;

  if(argc != 6){
    fprintf(stderr, "Usage: %s string1 string2 string3 host port\n",argv[0]);
    return -1;
  }
  portnum = (u_port_t)atoi(argv[5]);
  if((fd = u_connect(portnum, argv[4])) == -1){
    perror("Failled to establish connection");
    return 1;
  }
  fprintf(stderr, "[%ld]:connection made to %s\n", (long)getpid(), argv[4]);
  if((write(fd, argv[3], strlen(argv[3])+1)) == -1){
    fprintf(stderr, "Failed to write %s to fd", argv[3]);
    r_close(fd);
    return 0;
  }
  if((write(fd, argv[1], strlen(argv[1])+1)) == -1){
    fprintf(stderr, "Failed to write %s to fd", argv[1]);
    r_close(fd);
    return 0;
  }
  if((write(fd, argv[2], strlen(argv[2])+1)) == -1){
    fprintf(stderr, "Failed to write %s to fd", argv[2]);
    close(fd);
    return 0;
  }
  fprintf(stderr, "Everything has been written\n");
  return 0;
}

服务器.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "func.h"
#include "uici.h"

int main(int argc, char *argv[])
{
   u_port_t portnumber;
   int listenfd;
   int fd;
   char client[MAX_CANON];
   int bytes_copied;
   pid_t child;

   if (argc != 2) {
      fprintf(stderr, "Usage: %s port\n", argv[0]);
      return 1;
   }

   portnumber = (u_port_t) atoi(argv[1]);
   if ((listenfd = u_open(portnumber)) < 0) {
      perror("Listen endpoint creation failed");
      return 1;
   }

   fprintf(stderr, "[%ld]: Waiting for the first connection on port %d\n",
                    (long)getpid(), (int)portnumber);
   for ( ; ; ) {
      if ((fd = u_accept(listenfd, client, MAX_CANON)) != -1) {
         fprintf(stderr, "[%ld]: A connection has been received from %s\n",
                 (long) getpid(), client);
         if ((child = fork()) == -1)
            perror("Could not fork a child");

         if (child == 0) {                            /* child code */
            r_close(listenfd);
            int MAXSZ = 1024;
            char str3[MAXSZ];
            char str1[MAXSZ];
            char str2[MAXSZ];
            int bytesread = 0;
            fprintf(stderr, "Beginning the reads\n");
            read(fd,str3, MAXSZ);
            fprintf(stderr, "Finished 1st read\n");
            read(fd,str1, MAXSZ);
            fprintf(stderr, "Finished 2nd read\n");
            read(fd,str2, MAXSZ);
            fprintf(stderr, "str3: %s\n",str3);
            fprintf(stderr, "str1 = %s\n",str1);
            fprintf(stderr, "str2 = %s\n",str2);
            close(fd);
            return 0;
         } else {                                    /* parent code */
            close(fd);
            while (waitpid(-1, NULL, WNOHANG) > 0) ;  /* clean up zombies */
         }
      }
      else
         perror("Accept failed");
   }
}
4

2 回答 2

0

注意:不保证readwrite将读取或写入文件描述符的所有数据,也不保证客户端正在写入的数据块将以相同的方式在服务器上读取。

您必须确保检查写入的字节并继续将数据写入 fd,直到您将它们全部写入。读取时,您必须让客户端发送某种标头数据来描述预期的数据量,或者在您的情况下,您可以一次读取 1 个字节并查找一个'\0'字符,指示结束细绳。

由于MAXSZ可能比您发送的字符串大,服务器可能会一次将所有字符串读取到第一个缓冲区中,然后阻止后续读取。

于 2016-04-22T15:29:00.757 回答
0

第一个孩子分叉关闭听众r_close(listenfd);

然后,当客户端发送argv[1]没有可用的侦听器时,我认为由于无效u_accept(listenfd, client, MAX_CANON)而返回错误。listenfd

于 2016-04-22T15:32:48.850 回答