/*linux socket server demo
*
*date:2016-2-10
*
*author:xiehaocheng
*
*/
#include<sys/types.h> /* basic system data types */
#include<sys/socket.h> /* basic socket definitions */
#include<arpa/inet.h> /* inet(3) functions */
#include<netinet/in.h> /* sockaddr_in{} and other Internet defns */
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<errno.h>
#include<stdarg.h>
#include<string.h>
#include<syslog.h>
typedef void (*SIG_FUNC)(int);
/*
* This function is to print debug message and 'errno'
*/
void err_exit(const char *msg, ...)
{
char buf[512];
va_list args;
va_start(args, msg);
vsprintf(buf, msg, args);
sprintf(buf+strlen(buf), ":%s", strerror(errno));
strcat(buf, "\n");
va_end(args);
printf("%s", (char *)buf);
fflush(stdout); /* fflush std buffer */
exit(1);
}
void sigpipe_handler(int sig)
{
printf("Get signal PIPE!\n");
}
/*
* Handler of SIGCHLD
* use waitpid to set wait noblock
*/
void sig_chld_handler(int signo)
{
pid_t pid;
int stat;
while((pid = waitpid(-1, &stat, WNOHANG)) > 0) /*waitpid is noblock*/
printf("child process terminated!--child pid = %d!\n",pid);
return;
}
/*
* Set signal handler for SIGCHLD,to wait child process,clean zombies
*/
int set_signal(int signo, SIG_FUNC func)
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (signo == SIGALRM) {
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
#endif
} else { //Only SIGALRM can interrupt the system call, otherwise we restart system call
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART; /* SVR4, 44BSD */
#endif
}
if (sigaction(signo, &act, &oact) < 0)
return(-1);
return 0;
}
void server_function(int fd)
{
/*handle I/O timeout*/
struct timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 0;
if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0 ||
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
{
printf("failed to setsockopt!\n");
exit(1);
}
/*handle with the connect fd
here just print something for test*/
printf("the connect fd is %d\n",fd);
printf("sleep 1 second and exit\n");
sleep(1);
close(fd);
/*************************/
}
ssize_t /* Read "n" bytes from a descriptor. */
readn(int fd, void *vptr, size_t n)
{
size_t nleft;
ssize_t nread;
char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nread = read(fd, ptr, nleft)) < 0) {
if (errno == EINTR)
nread = 0;/* and call read() again */
else
return(-1);
} else if (nread == 0)
break; /* EOF */
nleft -= nread;
ptr += nread;
}
return(n - nleft); /* return >= 0 */
}
ssize_t /* Write "n" bytes to a descriptor. */
writen(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
if (nwritten < 0 && errno == EINTR)
nwritten = 0; /* and call write() again */
else
return(-1); /* error */
}
nleft -= nwritten;
ptr += nwritten;
}
return(n);
}
/* The main function
*/
int main(int argc, char *argv[])
{
printf("enter server\n");
int listen_fd, connect_fd, value = 1;
pid_t pid;
struct sockaddr_in server_addr, client_addr;
if(set_signal(SIGCHLD, sig_chld_handler) == -1){ //Set signal handler to handle SIGCHLD
err_exit("signal SIGCHLD set error");
}
if (set_signal(SIGPIPE, sigpipe_handler) == -1){
err_exit("signal SIGPIPE set error!\n");
}
if((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
err_exit("new socket error"); //This function will ends exit
}
if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&value, sizeof(value))){
printf("setsockopt address reuseable error!\n");
}
memset(&server_addr, 0, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(3333);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(listen_fd, (struct sockaddr *)&server_addr,
sizeof(struct sockaddr)) == -1){
err_exit("socket bind error");
}
if(listen(listen_fd, 10) == -1){
err_exit("listen error");
}
for(;;){
int clilen = sizeof(struct sockaddr_in);
printf("accept... \n");
if ((connect_fd = accept(listen_fd, (struct sockaddr *)&client_addr,
(socklen_t *)&clilen)) == -1){
if (errno == EINTR){
printf("interrupt by signal!\n");
} else if (errno == ECONNABORTED){
printf("ECONNABORTED\n");
} else {
printf("accept system call error!\n");
exit(1);
}
continue;
}
printf("server received a connection from %s \n", inet_ntoa(client_addr.sin_addr));
if ((pid = fork()) < 0){
err_exit("fork() error");
exit(1);
} else if (pid == 0){ /* child process */
close(listen_fd);
server_function(connect_fd);
exit(0);
}
close(connect_fd); /* parent closes connected socket */
}
}
一个简单的网络服务端demo示例
最新推荐文章于 2024-03-09 12:48:40 发布