-1

我的客户端-服务器应用程序中发生了一些奇怪的事情。请看一下这些简单的分叉客户端/服务器:客户端:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/wait.h>


#define IP_SERVER "192.168.1.89"
#define PORT_SERVER 65000
#define BUFFERSIZE 1024
#define NUMFILES 3


double timeElapsed(struct timeval* before, struct timeval* after) {

  return after->tv_sec - before->tv_sec + (double) (after->tv_usec - before->tv_usec)/1000000;
}


void getFile(char *request, struct sockaddr_in server) {

  char buffer[1024];
  int sockProc, res;
  int file;
  int sizeServ = sizeof(server);
  int writeFile;

  sockProc = socket(AF_INET, SOCK_STREAM, 0);

  if (sockProc < 0) {
      printf("Error on creating socket client\n");
      perror("");
      exit(1);
  }

  file = open(request, O_CREAT | O_WRONLY, S_IRWXU);


  res = connect(sockProc, (struct sockaddr*)&server, (socklen_t)sizeServ);
  if (res < 0) {
      printf("Error on connecting to server!\n");
      perror("");
      exit(1);
  }

  res = send(sockProc, (void*)request, strlen(request), 0);

  memset(buffer, 0, sizeof(buffer));

  while((res = recv(sockProc, (void*)buffer, sizeof(buffer), 0)) > 0) {
      write(file, (void*)buffer, strlen(buffer));
      memset(buffer, 0, sizeof(buffer));
  }


  close(sockProc);
  close(file);
  return;

  }


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

  int sockCli, res, i;

  struct sockaddr_in server;
  int sizeServ = sizeof(server);
  memset(&server, 0, sizeof(server));
  server.sin_family = AF_INET;
  inet_pton(AF_INET, IP_SERVER, &server.sin_addr);
  server.sin_port = htons(PORT_SERVER);

  char files[NUMFILES][32];
  char nameFile[32];

  char command[32] = "rm *.txt";

  system(command);

  struct timeval begin;
  struct timeval end;

  pid_t processes[NUMFILES];



  for(i = 0; i<NUMFILES; i++) {

      memset(nameFile, 0, sizeof(nameFile));
      printf("Inserisci nome file (con estensione) da ricevere:\n");
      scanf("%s", nameFile);
      strcpy(files[i], nameFile);

  }


  gettimeofday(&begin, NULL);

  for(i=0; i<NUMFILES; i++) {

      pid_t child = fork();

      if(child == 0) {
          getFile(files[i], server);
          exit(0);
      }

      else {
          processes[i] = child;
          continue;
      }

  }


  /*for(i=0; i<NUMFILES; i++) {
      waitpid(processes[i], NULL, 0);
  }*/

  wait(NULL);

  gettimeofday(&end, NULL);
  printf("Time elapsed on TCP is %f seconds\n", timeElapsed(&begin, &end));
  return 0;

  }

和服务器:

#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>

#define IP_SERVER "192.168.1.89"
#define PORT_SERVER 65000
#define BUFFERSIZE 1024

void execRequest(int* sockCli, struct sockaddr_in* client) {

  char buffer[BUFFERSIZE];
  char request[BUFFERSIZE];
  int res;

  memset(request, 0, sizeof(request));

  res = recv(*sockCli, (void*)request, sizeof(request), 0);

  if(res < 0) {
      printf("Error on recv()\n");
      perror("");
      exit(1);
  }
  printf("Requested file %s\n", request);

  char resource[32] = "files/";
  strcat(resource, request);

  int file = open(resource, O_RDONLY);

  if (file < 0) {
      printf("File %s does not exist\n", request);
      exit(1);
  }

  memset(buffer, 0, sizeof(buffer));

  while((res = read(file, (void*)buffer, sizeof(buffer))) > 0) {
      send(*sockCli, (void*)buffer, strlen(buffer), 0);
      memset(buffer, 0, sizeof(buffer));
  }

  close((*sockCli));
  close(file);
  free(sockCli);
  free(client);

  return;

  }

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

  int sockServ, i, res;
  int *sockCli;

  struct sockaddr_in server;
  struct sockaddr_in* client;


  sockServ = socket(AF_INET, SOCK_STREAM, 0);

  if(sockServ < 0) {
      printf("Error in creating socket\n");
      perror("");
      exit(1);
  }

  memset(&server, 0, sizeof(server));
  server.sin_addr.s_addr = inet_addr(IP_SERVER);
  server.sin_port = htons(PORT_SERVER);
  server.sin_family = AF_INET;

  int reuse = 1;
  res = setsockopt(sockServ, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
  if (res < 0) {
      printf("setsockopt() REUSEADDR failed\n");
      perror("");
      exit(1);
  }

  res = bind(sockServ, (struct sockaddr*)&server, sizeof(server));
  if (res < 0) {
      printf("Error on bindind TCP server!\n");
      perror("");
      exit(1);
  }

  res = listen(sockServ, 5);
  if (res < 0) {
      printf("Error on listening TCP server!\n");
      perror("");
      exit(1);
  }

  while(1) {

      sockCli = (int*)malloc(sizeof(int));
      client = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
      int sizeClient = sizeof(struct sockaddr_in);

      *sockCli = accept(sockServ, (struct sockaddr*)client, &sizeClient);

      if ((*sockCli) < 0) {
                printf("accept() failed\n");
        perror("");
        continue;
      }

      printf("Connected to %s:%d\n", inet_ntoa(client->sin_addr), client->sin_port);

      if( !fork() ) {

          execRequest(sockCli, client);
          exit(0);

      }

      else
          continue;



}

  return 0;


  }

这很奇怪。即使服务器关闭套接字,客户端创建的进程也不会终止,因此 recv() 应该返回 0 并让客户端进程退出循环。此外,读取文件有一些奇怪的地方:服务器只是读取 files.txt,但在执行此操作时,它在读取的字符中包含字符串“.txt”并将所有这些混合物发送给客户端……为什么?它们是简单的文件单字符,例如 aaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaa

但服务器读取并发送:

aaaaaaaaaaaaaaaaaa.txt aaaaaaaaaaaaaaaaaa

我能解决这一切吗?

4

2 回答 2

1

您不能使用strlen(buffer),仅仅因为您正在从文本文件中加载字符并不意味着buffer它将是一个有效的字符串,除非您采取措施确保它是有效的。而你没有;没有终止,因为您可以buffer使用文件中的数据填充所有内容。

于 2013-03-28T12:37:57.200 回答
0

我们必须在 Stack Overflow 上播放多少次破纪录?不要施放 malloc

我将此错误归咎于未能阅读手册,找出要包含的标题字符串是什么(以及 strlen/strcat/str*{anything}* 对其输入的期望,printf 对参数的期望对应于%s格式说明符等)以及read/recv 产生的内容。

res = recv(*sockCli, (void*)request, sizeof(request), 0);
if(res < 0) {
    printf("Error on recv()\n");
    perror("");
    exit(1);
}
printf("Requested file %.*s\n", res, request); // NOTE the field width provided by 'res'

根据手册,例如res = read(file, (void*)buffer, sizeof(buffer))应该存储错误或长度的示例。条件确保代码只有在它是一个长度send值时才会执行,那么为什么不把它当做一个呢??send(*sockCli, (void*)buffer, res, 0);

这些问题的出现似乎表明你的学习方法行不通。你在看哪本书?不看书学习 C 有点像不交流就知道哪些浆果有毒。

于 2013-03-28T13:06:25.520 回答