我正在进行一项分配,其中服务器分叉了多个子节点,每个传感器连接到服务器一个(并且每个子节点都有一个到该传感器节点的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);
}
}
答案 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()
是如何完成的。)