IO多路复用的网络通信

#ifndef __COMMON__

#define __COMMON__

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/select.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <signal.h>
#include <pthread.h>

#include "packet.h"
#include "common.h"

#define LISTEN_QUEUE_NUM 5
#define BUFFER_SIZE 256

#define RET_OK 0
#define RET_ERR -1
#define LISTEN_QUEUE_NUM 5
#define BUFFER_SIZE 256
#define ECHO_PORT 2029

#define PATH "/proc/pid/status"

int server();


#endif

 

//===========================================================================================================================================

#ifndef __PACKET__
#define __PACKET__

#define CMD_SHELL 0
#define CMD_USERVERI 1

#define REQUEST 't'
#define RESPONSE 'r'

struct Packet_Header {
char type;
int cmd;
int length;
};

/*
struct User {
char name[32];
char pass[32];
struct User *next;
};
*/
char * en_packet(struct Packet_Header *head, char *data) ;
char * de_packet(char *pkg, struct Packet_Header *head) ;
int send_packet(int socket, char type, int cmd, char *data);
char * get_packet(int socket, struct Packet_Header *head);
int process_packet(int socket, struct Packet_Header *head, char *data);


#endif

//===========================================================================================================================================

#include "common.h"
/*
input params: head,
output params: data
return value: pkg

*/
char * en_packet(struct Packet_Header *head,char *data)
{
void *pkg = malloc(head->length+sizeof(struct Packet_Header));
if (pkg == NULL) {
perror("malloc error");
exit(-1);
}
if (memcpy(pkg, head, sizeof(struct Packet_Header))==NULL)
{
perror("memcpy error");
exit(-1);
}

char *tmp = pkg;
tmp += sizeof(struct Packet_Header);

if(memcpy(tmp, data, head->length)==NULL)
{
perror("memcpy error");
exit(-1);
}
return (char *)pkg;
}
/*
input params: pkg,
output params: head
return value: data of pkg

*/
char * de_packet(char *pkg, struct Packet_Header *head)
{
void *res;
int len = 0;
if (memcpy(head, pkg, sizeof(struct Packet_Header)))
{
perror("memcpy header error");
exit(-1);
}

res = pkg + sizeof(struct Packet_Header);
len = head->length;
char *data = (char *)malloc(len);
if (data == NULL )
exit(-1);

if (memcpy(data, res, len))
{
perror("memcpy data error");
exit(-1);
}
return data;
}

/*
input params: socket,type,cmd, data
output params:
return value: int

*/
int send_packet(int socket, char type, int cmd, char *data)
{
char buf[BUFFER_SIZE];
char *pkg = buf;
int len;
//printf("send_packet +\n");
struct Packet_Header *head = malloc(sizeof(struct Packet_Header));
if (head == NULL)
{
perror("malloc error in send_packet");
return -1;
}

head->type = type;
head->cmd = cmd;
head->length = sizeof(buf);

len = sizeof(struct Packet_Header) + sizeof(buf);//length of packet

if ((pkg = en_packet(head, data) )== NULL)
{
perror("en_packet error in en_packet");
return -1;
}

if (write(socket, pkg, len) < 0)
{
perror("write error in send_packet");
return -1;
}
//printf("send packet success\n");
return 0;
}

/*
input params: socket, head
output params: head
return value: packet data pointer
*/
char * get_packet(int socket, struct Packet_Header *head)
{
int bytesread;
//void buf[BUFFER_SIZE];

if( (bytesread = read(socket, head, sizeof(struct Packet_Header))) < 0)
{
perror("read");
exit(-1);
}
else if(bytesread == 0)
{
fprintf(stderr, "server disconnect\n");
return NULL;
}

//struct Packet_Header *head = (struct Packet_Header *)buf;

char*data = (char *)malloc(head->length);
if (data == NULL) {
perror("malloc error");
exit(-1);
}

if( (bytesread = read(socket, data, head->length) )< 0)
{
perror("read");
exit(-1);
}
else if(bytesread == 0)
{
fprintf(stderr, "server disconnect\n");
return NULL;
}
printf("get packet\n");
return data;
}

int process_packet(int socket, struct Packet_Header *head, char *data)
{
char type;
int cmd;
FILE *fp = NULL;
char buf[BUFFER_SIZE];
int i;
//printf("process_packet +\n");

type = head->type;
cmd = head->cmd;
//printf("the type is %c\n", type);
if (type == REQUEST) //server received a request packet from client
{
printf("this is request packet!\n");
switch (cmd)
{
case CMD_SHELL:
printf("CMD_SHELL packet!\n");

fp = popen(data, "r");
if (fp == NULL)
{
perror("popen");
return -1;
}
while (fgets(buf, sizeof(buf), fp) != NULL)
{
if (send_packet(socket, RESPONSE, CMD_SHELL, buf) < 0)
{
perror("send_packet");
return -1;
}
//printf("%s\n", buf);
}
pclose(fp);
printf("Response CMD_SHELL packet finished!\n");
break;

case CMD_USERVERI:
printf("CMD_USERVERI packet!\n");
break;
default:
printf("wrong packet cmd!\n");
break;
}
}
else if (type == RESPONSE) //client received a response packet from server
{
printf("this is response packet!\n");
switch (cmd)
{
case CMD_SHELL:
printf("CMD_SHELL packet!\n");
for (i=0;i<head->length;i++)
printf("%c", *data++);
break;
case CMD_USERVERI:
printf("CMD_USERVERI packet!\n");
break;
default:
printf("wrong packet cmd!\n");
break;
}

}
return 0;
}

 //=========================================================================================================================================

#include "common.h"
int main(int argc, char **argv)
{
int sock, maxfd = 0;
struct sockaddr_in servaddr;
struct hostent *server;
fd_set rset, set;
int nfound;
struct Packet_Header head;
char buf[BUFFER_SIZE];
char *p=buf;
int opt=1;

if (argc < 2)
{
fprintf(stderr,"usage %s hostname\n", argv[0]);
return RET_ERR;
}
if((server = gethostbyname(argv[1])) == NULL)
{
herror("gethostbyname. ");
return RET_ERR;
}
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket");
return -1;
}
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
{
perror("ERROR setsockopt");
return -1;
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr =htonl(INADDR_ANY);
servaddr.sin_port = htons((uint16_t)ECHO_PORT);
if (connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
perror("connect");
return -1;
}
maxfd = fileno(stdin);
FD_ZERO(&set);
FD_SET(sock, &set);
FD_SET(maxfd, &set);
maxfd = (maxfd > sock ? maxfd : sock) + 1;
while(1)
{
rset = set;
if ((nfound = select(maxfd, &rset, (fd_set *)0, (fd_set *)0, NULL)) < 0)
{
if (errno == EINTR) {
fprintf(stderr, "interrupted system call\n");
continue;
}
perror("select");
exit(1);
}
if (FD_ISSET(fileno(stdin), &rset))
{
//printf("Pls enter the command to server:\n");
memset(buf, 0, sizeof(buf));
if (fgets(buf, sizeof(buf), stdin) == NULL) {
if (ferror(stdin)) {
perror("stdin");
return -1;
}
return -1;
}
//printf("hkdsjgk\n");
if (send_packet(sock, REQUEST, CMD_SHELL, buf) < 0)
{
perror("send_packet");
return -1;
}

}
if (FD_ISSET(sock,&rset))
{
printf("received the packet\n");
if((p = get_packet(sock, &head)) == NULL)
{
perror("get_packet");
exit(-1);
}
//memset(buf, 0, sizeof(buf));
strncpy(buf, p, strlen(p));
process_packet(sock, &head, buf);
memset(buf, 0, sizeof(buf));
}
}
return 0;
}

 //==========================================================================================================================================

#include "common.h"
int server()
{
struct sockaddr_in servaddr, remote;
int request_sock, new_sock;
int nfound, fd, maxfd;
uint32_t addrlen;
fd_set rset, set;
struct timeval timeout;
char buf[BUFFER_SIZE]="";
char *p=buf;
struct Packet_Header head;
int ret;
int opt = 1;

if ((request_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("socket");
return -1;
}
if (setsockopt(request_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
{
perror("ERROR setsockopt");
return -1;
}

memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr =htonl(INADDR_ANY);
servaddr.sin_port = htons((uint16_t)ECHO_PORT);

if (bind(request_sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
perror("bind");
return -1;
}
if (listen(request_sock, LISTEN_QUEUE_NUM) < 0)
{
perror("listen");
return -1;
}

FD_ZERO(&set);
FD_SET(request_sock, &set);
maxfd = request_sock;
while(1) {
rset = set;
timeout.tv_sec = 0;
timeout.tv_usec = 500000;
if((nfound = select(maxfd + 1, &rset, (fd_set *)0, (fd_set *)0, &timeout)) < 0)
{
perror("select");
return -1;
}
else if (nfound == 0)
{
printf(".");
fflush(stdout);
continue;
}
if (FD_ISSET(request_sock, &rset))
{
addrlen = sizeof(remote);
if ((new_sock = accept(request_sock, (struct sockaddr *)&remote, &addrlen)) < 0)
{
perror("accept");
return -1;
}
printf("connection from host %s, port %d, socket %d\r\n",
inet_ntoa(remote.sin_addr), ntohs(remote.sin_port),
new_sock);
FD_SET(new_sock, &set);
if (new_sock > maxfd)
maxfd = new_sock;
FD_CLR(request_sock, &rset);
nfound --;
}
for (fd=0; fd <= maxfd && nfound > 0; fd++) {
if (FD_ISSET(fd, &rset)) {
nfound --;
if ((p = get_packet(fd, &head)) == NULL)
{
fprintf(stderr,"server: end of file on %d\r\n", fd);
FD_CLR(fd, &set);
close(fd);
continue;
}
//memset(buf, 0, sizeof(buf));
strncpy(buf, p, strlen(p));
printf("buf is %s\n", buf);
ret = process_packet(fd, &head, buf);
memset(buf, 0, sizeof(buf));
if (ret < 0)
{
FD_CLR(fd, &set);
close(fd);
exit(-1);
}

}
}
}
return 0;
}

// ==========================================================================================================================================

#include "common.h"
pid_t server_pid = -1;
static void sig_routine(int signo)
{
switch(signo)
{
case SIGCHLD:
while(waitpid(-1,NULL,WNOHANG) > 0);
break;
}
return;
}

void make_daemon()
{
pid_t pid;
int stdin_fd;
int stdout_fd;
int stderr_fd;

if ((pid=fork()) != 0)
exit(0);
setsid();
signal(SIGHUP,SIG_IGN);
signal(SIGHUP,sig_routine);

if ((pid=fork()) != 0) exit(0);
stdin_fd = open("../config/stdin_log",O_WRONLY);
stdout_fd = open("../config/stdout_log",O_WRONLY);
stderr_fd = open("../config/stderr_log",O_WRONLY);
dup2(stdin_fd, 0);
dup2(stdout_fd, 1);
dup2(stderr_fd, 2);

umask(0);
}
void start_server()
{
pid_t pid;

if (server_pid > 0)
{
if (kill(server_pid,SIGKILL) == -1)
{
if (errno != ESRCH)
{
server_pid = -1;
return;
}
server_pid = -1;
return;
}
printf("if the process is running, now kill [%d]\n",server_pid);
server_pid = -1;
}

pid = fork();
if (pid == 0)
{
server();
exit(0);
} else if (pid > 0) {
server_pid = pid;
printf("the child process is %d\n",pid);
} else {
server_pid = -1;
return;
}
}

void stop_server()
{
if (server_pid > 0)
{
kill(server_pid, SIGKILL);
printf("stop process %d\n",server_pid);
server_pid = -2;
}
}

void check_server()
{
int nr = 0;
char stat[128];

if (server_pid == -1)
{
start_server();
} else if (server_pid >0) {

nr = open(PATH,O_RDONLY);
if(nr == 0)
return;

if(read(nr,stat,128) <=0)
return;

char *ptr = strstr(stat,"State");
if(ptr == NULL)
return;

ptr += 7;
switch(*ptr)
{
case 'Z':
wait(NULL);
printf("服务器进程异常,回收后重新启动服务器\n");
start_server();
break;
}
}
}
int main()
{
make_daemon();
printf("the current PID is:%d\n", getpid());

signal(SIGUSR1,start_server);
signal(SIGUSR2,stop_server);
signal(SIGALRM,check_server);

start_server();

while (1)
{
sleep(5);
alarm(4);
if (server_pid > 0)
waitpid(-1,NULL,WNOHANG);
}
}

============================================================================================================================================

 

/*test.c
send SIGUSR1 and SIGUSR2 to test the case.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
pid_t pid;
int num;

printf("Pls enter the PID:\n");
scanf("%d", &pid);

printf("enter 1 send SIGUSR1\n");
printf("enter 2 send SIGUSR1\n");
scanf("%d", &num);

switch (num) {
case 1:
kill(pid, SIGUSR1);
break;
case 2:
kill(pid, SIGUSR2);
break;
default:
break;

}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*test.csend SIGUSR1 and SIGUSR2 to test the case.*/#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <sys/types.h>#include <sys/wait.h>
int main(){pid_t pid;int num;
printf("Pls enter the PID:\n");scanf("%d", &pid);
printf("enter 1 send SIGUSR1\n");printf("enter 2 send SIGUSR1\n");scanf("%d", &num);
switch (num) {case 1:kill(pid, SIGUSR1);break;case 2:kill(pid, SIGUSR2);break;default:break;
}}

 

posted on 2017-08-22 17:13  ML-创客猿  阅读(201)  评论(0)    收藏  举报