C fork()孩子被杀或在永恒的循环中?

时间:2014-05-02 09:27:46

标签: c tcp fork

我正在进行一项分配,其中服务器分叉了多个子节点,每个传感器连接到服务器一个(并且每个子节点都有一个到该传感器节点的tcp连接)。

现在因为这是我第一次使用fork,我并不完全确定它是否正常工作。

tcpsocket.h是提供的文件,提供了一些基本的tcp功能。这是有效的,因为数据是成功发送和接收的。

以下是代码的简短说明:主进程被动地侦听传入的tcp连接。 tcp_wait_for_connection()在阻塞模式下等待建立连接。一旦完成,它应该给一个新孩子的连接。孩子当然应该关闭端口的被动监听,主要过程不应该听传感器的连接。

现在一切正常,但我不确定孩子是否被正确杀死。例如,一个sensorNode退出(cntrl + c),因此连接停止,但我不确定孩子是否会死亡或继续循环永恒。我还包括tcpsocket.c,因为这可能会更清晰。

server.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

#include "tcpsocket.h"

#define BUFSIZE 1024
#define PORT 1234

struct package{
    unsigned sensorId:12;
    unsigned sequence:4;
    unsigned flag:2;
    unsigned sign:1;
    unsigned value:12;
    unsigned parity:1;
};

typedef struct package packs;

union sensor{
    packs pack;
    unsigned sensorValue;
};

typedef union sensor Sensor;

char buffer[BUFSIZE];

int main( void )
{
    Socket server, client;
    int bytes;

    server = tcp_passive_open( PORT );

    while( 1 ) {
        client = tcp_wait_for_connection( server );

        #ifdef DEBUG
            printf("Incoming client connection\n");
        #endif

        pid_t pid;
        pid = fork();

        if(pid == -1){
            printf("Something went wrong creating a child.\n");
        }else if(pid == 0){
            tcp_close( &server );

            #ifdef DEBUG
                pid_t parentPid;
                parentPid = getppid();
                printf("New child created with parent id %d, own pid: %d\n",parentPid, pid);
            #endif

            Sensor * mySensor = malloc(sizeof(packs));

            while(1){
                memset(buffer, 0, BUFSIZE);

                bytes = tcp_receive( client, (void *)buffer, BUFSIZE );

                if(bytes > 0){
                    mySensor->sensorValue = atoi(buffer);
                    #ifdef DEBUG
                        printf("Received message of %d bytes. ID: %i, Sequence: %i, flag: %i, sign: %i, value: %i\n", 
                            bytes, mySensor->pack.sensorId, mySensor->pack.sequence, mySensor->pack.flag, mySensor->pack.sign, mySensor->pack.value);
                    #endif
                }
            }
            tcp_close( &client );
            exit(0);
        }
        tcp_close( &client );
    }
    tcp_close( &server );
    return 0;
}

tcpsocket.c

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "tcpsocket.h"

#define CHAR_IP_ADDR_LENGTH 16     // 4 numbers of 3 digits, 3 dots and \0
#define ERROR_SD -1
#define ERROR_PORT 0
#define MIN_PORT 1
#define MAX_PORT 65536

#define PROTOCOLFAMILY  AF_INET     // internet protocol suite
#define TYPE        SOCK_STREAM // streaming protool type
#define PROTOCOL    IPPROTO_TCP     // TCP protocol 

typedef struct {
  int sd;
  char *ip_addr;
  int port;   
  } MySocket;       // My definition of a socket: a socket descriptor, 
            // the IP address and port number of the PC hosting this socket 

// private functions used for error checking
static void die(char* message);
static void check_socket_ptr(char *pre_msg, Socket s);
static void check_sd(char *pre_msg, int sd);
static void check_ip_addr(char *pre_msg, char *ip_addr);
static void check_port(char *pre_msg, int port);

// private error message string
static char error_msg[256]; 

/*-------------------------------------------------------------------------------------*/
Socket tcp_passive_open(int port) 
/*-------------------------------------------------------------------------------------*/
{
  // parameter check                                                                                         
  check_port("tcp_open_server() failed", port);

  MySocket *s = (MySocket *)malloc( sizeof(MySocket) );
  if ( s == NULL ) 
    die("tcp_open__socket() failed: mem alloc error");

  struct sockaddr_in addr;

  s->sd = socket(PROTOCOLFAMILY, TYPE, PROTOCOL);
  check_sd("tcp_open_server failed(): socket creation error", s->sd);

  /* Construct the server address structure */
  memset(&addr, 0, sizeof(struct sockaddr_in));
  addr.sin_family = PROTOCOLFAMILY;
  addr.sin_addr.s_addr = htonl(INADDR_ANY);
  addr.sin_port = htons(port);

  if ( bind(s->sd, (struct sockaddr *)&addr, sizeof(addr)) != 0 ) {
    die("tcp_open_server failed(): bind() failed");  //will fail if e.g; port is in use
  }

  if( listen(s->sd, MAX_PENDING) != 0 )
    die("tcp_open_server failed(): listen() failed");

  s->port = port;
  s->ip_addr = NULL;  //INADDR_ANY ...  

  return (Socket)s;  
}

/*-------------------------------------------------------------------------------------*/
Socket tcp_active_open( int remote_port, char *remote_ip ) 
/*-------------------------------------------------------------------------------------*/
{
  // parameter check                                                                                         
  check_port("tcp_open_client() failed", remote_port);
  check_ip_addr("tcp_open_client() failed", remote_ip);

  MySocket *client = (MySocket *)malloc( sizeof(MySocket) );
  if ( client == NULL ) 
    die("tcp_open_client() failed: mem alloc error");

  struct sockaddr_in addr;
  int length;
  char *p;

  client->sd = socket(PROTOCOLFAMILY, TYPE, PROTOCOL);
  check_sd("tcp_open_client() failed: socket creation error", client->sd);

  /* Construct the server address structure */
  memset(&addr, 0, sizeof(struct sockaddr_in));
  addr.sin_family = PROTOCOLFAMILY;
  if ( inet_aton(remote_ip, (struct in_addr *) &addr.sin_addr.s_addr) == 0 ) 
    die("tcp_open_client failed(): invalid ip address");

  addr.sin_port = htons(remote_port);

  if ( connect(client->sd, (struct sockaddr *) &addr, sizeof(addr) ) < 0 )
    die("tcp_open_client failed(): connect () failed");

  memset(&addr, 0, sizeof(struct sockaddr_in));
  length = sizeof(addr);
  if ( getsockname(client->sd, (struct sockaddr *)&addr, (socklen_t *)&length) != 0 )
    die("tcp_open_client failed(): getsockname() failed");

  p = inet_ntoa(addr.sin_addr);  //returns addr to statically allocated buffer

  client->ip_addr = (char *)malloc( sizeof(char)*CHAR_IP_ADDR_LENGTH);
  if ( client->ip_addr == NULL )
    die("tcp_open_client failed(): mem alloc error");
  client->ip_addr = strcpy( client->ip_addr, p );
  client->port = ntohs(addr.sin_port);

  return (Socket)client;
}

/*-------------------------------------------------------------------------------------*/
Socket tcp_wait_for_connection( Socket socket ) 
/*-------------------------------------------------------------------------------------*/
{
  // parameter check                                                                                         
  check_socket_ptr("tcp_wait_for_connection() failed", socket);

  MySocket *serv = (MySocket *)socket;
  MySocket *clie = (MySocket *)malloc( sizeof(MySocket) );
  if ( clie == NULL ) 
    die("tcp_wait_for_connection() failed: mem alloc error");

  struct sockaddr_in addr;
  unsigned int length = sizeof(struct sockaddr_in);
  char *p;

  check_sd("tcp_wait_for_connection() failed", serv->sd);

  clie->sd = accept(serv->sd, (struct sockaddr*) &addr, &length);

  check_sd("tcp_wait_for_connection() failed: accept() error", clie->sd);

  p = inet_ntoa(addr.sin_addr);  //returns addr to statically allocated buffer
  clie->ip_addr = (char *)malloc( sizeof(char)*CHAR_IP_ADDR_LENGTH);
  if ( clie->ip_addr == NULL )
    die("tcp_wait_for_connection failed(): mem alloc error");
  clie->ip_addr = strcpy( clie->ip_addr, p );
  clie->port = ntohs(addr.sin_port);

  return (Socket)clie;
}

/*-------------------------------------------------------------------------------------*/
void tcp_close( Socket *socket )
/*-------------------------------------------------------------------------------------*/
{
  // parameter check                
  check_socket_ptr("tcp_close() failed", socket);                                                                         
  check_socket_ptr("tcp_close() failed", *socket);

  MySocket *s = (MySocket *)*socket;

  check_sd("tcp_close() failed", s->sd);

  close( s->sd );

  free(s);

  *socket = NULL;
}

/*-------------------------------------------------------------------------------------*/
void tcp_send(Socket socket, void *buffer, int bufsize ) 
/*-------------------------------------------------------------------------------------*/
{
  // parameter check                                                                                         
  check_socket_ptr("tcp_send() failed", socket);

  if ( buffer == NULL ) 
    die("tcp_send failed(): buffer param is NULL");

  MySocket *s = (MySocket *)socket;
  int result;
  int sen = 0;
  int to_sen = bufsize;

  check_sd("tcp_send() failed", s->sd);

  do {
    result = send(s->sd, (const void*) (buffer+sen), to_sen, 0);
    if (result < 0)
      die("tcp_send() failed: not able to send");
    sen += result;
    to_sen -= result;
  } while ( to_sen > 0 );

}

/*-------------------------------------------------------------------------------------*/
int tcp_receive (Socket socket, void* buffer, int bufsize) 
/*-------------------------------------------------------------------------------------*/
{
  // parameter check                                                                             
  check_socket_ptr("tcp_receive() failed", socket);

  if ( buffer == NULL ) 
    die("tcp_receive() failed: buffer param is NULL");
  if ( bufsize == 0 ) 
    die("tcp_receive() failed: bufsize is zero");

  MySocket *s = (MySocket *)socket;

  check_sd("tcp_receive() failed", s->sd);

  int rec = recv(s->sd, buffer, bufsize, 0);

  return rec;
}

/*-------------------------------------------------------------------------------------*/
char * get_ip_addr( Socket socket ) 

/*-------------------------------------------------------------------------------------*/
{   
  // parameter check
  check_socket_ptr("get_ip_addr() failed", socket);

  MySocket *s = (MySocket *)socket;

  check_ip_addr("get_ip_addr() failed", s->ip_addr);

  return s->ip_addr;
}

/*-------------------------------------------------------------------------------------*/
int get_port( Socket socket ) 

/*-------------------------------------------------------------------------------------*/
{
  // parameter check
  check_socket_ptr("get_port() failed", socket);

  MySocket *s = (MySocket *)socket;

  check_port("get_port() failed", s->port);

  return s->port;
}


/*-------------------------------------------------------------------------------------*/
int get_socket_descriptor( Socket socket )
/*-------------------------------------------------------------------------------------*/
{
  // parameter check
  check_socket_ptr("get_socket_descriptor() failed", socket);

  MySocket *s = (MySocket *)socket;

  check_sd("get_socket_descriptor() failed", s->sd);

  return s->sd;
}


/*-------------------------------------------------------------------------------------*/
static void die(char* message)
/*-------------------------------------------------------------------------------------*/
{
  perror(message);
  exit(-1);
}

/*-------------------------------------------------------------------------------------*/
static void check_socket_ptr(char *pre_msg, Socket socket) 
/*-------------------------------------------------------------------------------------*/
{
  if ( socket == NULL ) 
  {
    sprintf(error_msg, "%s: socket ptr is NULL", pre_msg);
    die(error_msg);   
  }                                                                                      
}

/*-------------------------------------------------------------------------------------*/       
static void check_sd(char *pre_msg, int sd)
/*-------------------------------------------------------------------------------------*/
{ 
  if ( sd <= ERROR_SD ) 
  {
    sprintf(error_msg, "%s: invalid socket descriptor", pre_msg);
    die(error_msg); 
  } 
}

/*-------------------------------------------------------------------------------------*/
static void check_ip_addr(char *pre_msg, char *ip_addr)
/*-------------------------------------------------------------------------------------*/
{
  if ( ip_addr == NULL )
  { 
    sprintf(error_msg, "%s: invalid socket ip address", pre_msg);
    die(error_msg);
  } 
}

/*-------------------------------------------------------------------------------------*/
static void check_port(char *pre_msg, int port)
/*-------------------------------------------------------------------------------------*/
{
  if ( (port < MIN_PORT) || (port > MAX_PORT) )
  {
    sprintf(error_msg, "%s: invalid socket port", pre_msg);
    die(error_msg);
  } 
}

1 个答案:

答案 0 :(得分:3)

  

我不确定这个孩子是否会死亡或永远不停地循环。

在您显示的代码中,没有recv()返回0的测试,这表示该连接已被另一方关闭。

您可能希望像这样修改代码

            if(bytes > 0){
                mySensor->sensorValue = atoi(buffer);
                #ifdef DEBUG
                    printf("Received message of %d bytes. ID: %i, Sequence: %i, flag: %i, sign: %i, value: %i\n", 
                        bytes, mySensor->pack.sensorId, mySensor->pack.sequence, mySensor->pack.flag, mySensor->pack.sign, mySensor->pack.value);
                #endif
            }
            else if (bytes == 0)
            {
              printf("Connection closed by other side. Exiting ...\n");
              break;
            }
            else /* bytes < 0 */
            {
              printf("Error receiving. Exiting ...\n");
              break;
            }

结束孩子。没有必要杀死&#34;在发送SIGKILL信号方面的任何过程,顺便说一句。


同样,tcp_receive()函数未能测试每次调用recv()时收到的数据量,然后在必要时循环recv(),直到收到所有请求的数据为止。 (请参阅tcp_send(),了解send()是如何完成的。)