[root@bob work]# gcc download.c
download.c:36: two or more data types in declaration of `init_child'
download.c:36: two or more data types in declaration of `init_child'
download.c:36: two or more data types in declaration of `init_child'
download.c:36: two or more data types in declaration of `init_child'
download.c:36: two or more data types in declaration of `init_child'
download.c:36: two or more data types in declaration of `init_child'
download.c:36: two or more data types in declaration of `init_child'
download.c:36: two or more data types in declaration of `init_child'
看了半天, 也没有不知道为什么?? 谢谢大家帮忙。
整个程序如下:
/* ==========================================================
download.c
*==========================================================*/
/*
* run a daemon to accept download request from client
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> //socket ,bind , listen ,accept
#include <sys/socket.h>
#include <netinet/in.h> //inet_addr(char *p)
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h> //waitpid function
#include <errno.h> //errno
#include "download.h"
#define PORT 9000 //port of Download Server
#define MAX_SUPPORT_CLIENT 100
#define BIND_FAILURE -1
#define SOCKET_FAILURE -2
#define ACCEPT_FAILURE -3
#define RECIEVE_FAILURE -4
#define SEND_FAILURE -5
/*
* Generate a child process
*/
void init_child(void) {
pid_t pid = 0;
pid = fork();
if (pid < 0) {
printf("Program fork fail
");
exit(-1);
} else if (pid != 0) {
exit(0); /* parent goes bye-bye */
}
/* child continues */
setsid(); /* standard daemon procedure */
//for(i=0;i<64;i++)
// close(i);
close(0);
close(1);
close(2);
chdir("/");
umask(0);
}
void sigChildHandler(int signo)
{
int status;
wait(&status);
while(status > 0 || (status < 0 && errno==EINTR)) {
wait(&status);
}
}
int main(void)
{
struct sockaddr_in local_addr_in ;
struct sockaddr_in client_addr_in;
int sock_fd = 0;
int source_client_fd = 0;
int on = 1;
int address_size = 0;
int rc = 0; //the return value of all socket operation
struct sigaction sig_act; //you must define a sigaction that will be associated with
a SIGCHLD
init_child(); //the main process will become a daemon
sock_fd = socket(AF_INET, SOCK_STREAM, 0); /* create a socket */
/* the sock_fd is blocked ,you can set it non-block ,
* with fuction fcntl,fcntl(sock_fd,F_SETFL,O_NONBLOCK);
*/
if(sock_fd < 0)
{
perror("Creating Socket Error!
");
exit(SOCKET_FAILURE);
}
//add setsockopt , you can lose the messages "address already used"
if( setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,&on, sizeof(int)) < 0)
{
perror("setsockopt error
");
exit(-1);
}
memset(&local_addr_in,' ',sizeof(local_addr_in));
local_addr_in.sin_family = AF_INET;
local_addr_in.sin_addr.s_addr = htonl(INADDR_ANY); //automatically fill with my IP
Address
local_addr_in.sin_port = htons(PORT);
//maybe , you should empty local_addr_in.sin_zero
memset((char *)&(local_addr_in.sin_zero),' ',8);
rc = bind(sock_fd,(struct sockaddr *)&local_addr_in,sizeof(struct sockaddr));
if(rc < 0) {
perror("bind failure
");
exit(BIND_FAILURE);
}
sig_act.sa_handler = sigChildHandler ;
sigemptyset(&sig_act.sa_mask);
sig_act.sa_flags = SA_RESTART;
/* -------------register signal handler ---------*/
if( sigaction(SIGCHLD,&sig_act,NULL) < 0) {
perror("Register signal Handler Failure
");
exit(-1);
}
//begin to listen the requests from any client
listen(sock_fd,MAX_SUPPORT_CLIENT); //accept 20 connection
printf("Begin to be accepting downloading request ...................
");
//----------Begin to deal with request from Client ----------
while(1) //it will looply deal the client's connection continously
{
pid_t child_pid = 0;
source_client_fd = accept(sock_fd,(struct sockaddr
*)&client_addr_in,&address_size);//address_size is no usefull
if(source_client_fd < 0) {
perror("Accept from clients failure !
");
exit(ACCEPT_FAILURE);
}
//into child process
child_pid = fork();
if(child_pid < 0) { //fork failure
perror("fork() failure ");
exit(-1);
}
else if(child_pid == 0) { //into child process
unsigned char buffer[255]; //this buffer will contain the cmd content ,so it must
unique ,when want to send , rewrite the buffer
struct DownloadPacket * Packet = NULL;
memset(buffer,' ',sizeof(buffer));
close(sock_fd); //child process doesn't need socket FD
//begin to recieve data from the temp socket descriptor
rc = recv(source_client_fd,buffer,sizeof(buffer)-1,0);
printf("recieve length is %i
",rc);
if(rc < 0) {
perror("recieve data from client ,failure !
");
exit(RECIEVE_FAILURE);
}
printf("Server has recieved data from %s , contents is %s
",
inet_ntoa(client_addr_in.sin_addr), buffer);
//-----------judge the CMD type ---------
Packet = (struct DownloadPacket *)buffer;
switch (Packet->cmd_type)
{
case SEARCH_DLSERVER_CMD : //client request NAS Download Server
;
break;
case DLREQUEST_CMD :
;
break;
case DLSTATUS_QUERY_CMD :
;
break;
default:
printf("this packet is a invalid packet
");
}
exit(0); //once the child process exited ,it will trigger SIGCHILD signal ,
//the kernel will call sigChildHandler function to reclaim the child process
} //end of else if
else {
close(source_client_fd); //parent doesn't need this socket fd ,which has been used
by child process
}
} //end of while(1)
return 0;
}
download.h 为:
/*
* Download Program , Author by bob_zhang
* Function : it is a server that can accept some download request from client
(typically in Windows) ,it really acts the download function
* and store them into \NAS_BIOSNAMEdiskdownloads directory
*
*download.h
*/
#define IP_MAX_LENGTH 16
#define URL_MAX_LENGTH 255
#define FILENAME_MAX_LENGTH 255
#define NETBIOSNAME_MAX_LENGTH 255
//error NO
#define DLOADING_OK 0
#define DLOADING_ERR -1
#define DLOADED_OK 0
enum cmd_type {
SEARCH_DLSERVER_CMD=0x01,//Windows client will search a NAS download Server
DLSERVER_ACK_CMD, //0x02, Download server give a ACK to client ,to represent its
status including NetBIOS name and IP
DLREQUEST_CMD, //0x03, Windows client will send a download request to NAS download
Server
DLACK_CMD, //0x04,NAS download server give a ACK to client 's downloading request
DLSTATUS_QUERY_CMD, //0x05,windows client will query NAS download server's status
,which file downloading status
DLSTATUS_ACK_CMD //0x06,NAS download server will represents its own status
}
struct SearchDownloadServerRequest {
char ClientIP[IP_MAX_LENGTH]; //only tell Server its own IP address
}
struct DownloadServerAck {
char NetBIOSName[NETBIOSNAME_MAX_LENGTH];
char DlServerIP[IP_MAX_LENGTH];
int RetValue;
}
struct DownloadRequest {
char ClientIP[IP_MAX_LENGTH];
char URLString[URL_MAX_LENGTH];
}
struct DownloadAck {
int RetValue ; //return value of excuting the downloading tool ,OK or fail
}
struct DownloadStatusQueryRequest {
char ClientIP[IP_MAX_LENGTH];
char URLString[URL_MAX_LENGTH];
}
struct DownloadStatusQueryAck {
char URLString[URL_MAX_LENGTH]; //for example, href=http://www.kernel.org/2.4.19.tar.gz>http://www.kernel.org/2.4.19.tar.gz
char FileName[FILENAME_MAX_LENGTH]; //for example , 2.4.19.tar.gz
char SavePath[255]; // \SCFD529Bdiskdownloads2.4.19.tar.gz
unsigned int FileSize ; //byte
unsigned int RecvByte; //byte
unsigned int RecvRate; //%
char ElapseTime[9]; //for example: 00:01:10 ,elapse 1minutes 10seconds
char LeftTime[9]; //for example: 01:09:07 , left time :1hour ,9 minutes ,7seconds
unsigned int AverageSpeed; //KB/s
int isFinished; //1: finished ,non-1:downloading
}
struct DownloadPacket {
unsigned int cmd_type ;
union {
struct SearchDownloadServerRequest SearchDownloadServerRequestPack ;
struct DownloadServerAck DownloadServerAckPack;
struct DownloadRequest DownloadRequestPack;
struct DownloadAck DownloadAckPack;
struct DownloadStatusQueryRequest DownloadStatusQueryRequestPack ;
struct DownloadStatusQueryAck DownloadStatusQueryAckPack;
}data;
}