进程无法终止

时间:2013-03-28 12:34:22

标签: c tcp

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

#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;

  }

和SERVER:

#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”,并将所有这些混合物发送给客户端...为什么? 它们是简单的文件单声道字符 aaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaa

但是服务器会读取并发送:

aaaaaaaaaaaaaaaaaa.txt aaaaaaaaaaaaaaaaaa

我可以解决这一切吗?

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

我们必须在Stack Overflow上播放多少次破坏的记录? Don't cast 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代码仅在 length 值时执行,那么为什么不将它作为一个? send(*sockCli, (void*)buffer, res, 0);

这些问题的出现似乎表明你的学习方法不起作用。你正在读哪本书?没有书就学习C有点像学习没有交流的浆果有毒。