学习 UNIX网络编程卷1:套接字 笔记1-实现一个简单的回射客户服务器程序

来源:互联网 发布:国家工商总局网络培训 编辑:程序博客网 时间:2024/05/17 03:34

一:客户端程序

1、头文件:unp.h


#ifndef _unp_h#define _unp_h#include <sys/types.h> /* basic system data types */#include <sys/socket.h> /* basic socket definitions */#include <sys/time.h> /* timeval{} for select() */#include <time.h>  /* timespec{} for pselect() */#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */#include <arpa/inet.h> /* inet(3) functions */#include <errno.h>#include <fcntl.h>  /* for nonblocking */#include <netdb.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/stat.h> /* for S_xxx file mode constants */#include <sys/uio.h>  /* for iovec{} and readv/writev */#include <unistd.h>#include <sys/wait.h>#include <sys/un.h>  /* for Unix domain sockets */#define MAXLINE 4096#define LISTENQ 5#define SERV_PORT   9877int Socket(int sockfd, int type, int protocol);void Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);void Listen(int sockfd,int backlog);void Connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);int Accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);void Write(int fd,void *buf,size_t count);void Close(int sockfd);void err_sys(char *err_str);int Fork();void str_echo(int sockfd);ssize_t writen(int fd, char *buf, size_t n);ssize_t Writen(int fd, char *buf, size_t n);void str_cli(FILE *fp, int sockfd);ssize_t readline(int fd, void *vptr, size_t maxlen);ssize_t Readline(int fd, void *vptr, size_t maxlen);#endif
2、客户端主程序:clien.c

#include "unp.h"int main(int argc,char **argv){    char ip_addr[20];    int sockfd;    struct sockaddr_in servaddr;    if (argc != 2)    {        err_sys("usage:clien <IPaddress>");        return -1;    }    bzero(&servaddr, sizeof(servaddr));    bzero(ip_addr,sizeof(ip_addr));    strcpy(ip_addr,argv[1]);    sockfd = Socket(AF_INET, SOCK_STREAM, 0);        servaddr.sin_family = AF_INET;    servaddr.sin_port = htons(SERV_PORT);    //servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");    servaddr.sin_addr.s_addr = inet_addr(ip_addr);    Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));    str_cli(stdin,sockfd);    return 0;}

3、客户端包裹函数:pack.c

#include "unp.h"void err_sys(char *err_str){  perror(err_str);}int Socket(int sockfd, int type, int protocol){  int n=0;  if ((n=socket(sockfd,type,protocol))<0)  {    err_sys("socket error");  }  return n;}void Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen){  int n=0;  if ((n = bind(sockfd,myaddr,addrlen))<0)  {    err_sys("bind error");  }}void Listen(int sockfd,int backlog){  char *ptr=NULL;  if ((ptr=getenv("LISTENQ"))!=NULL)  {    backlog=atoi(ptr);  }  if (listen(sockfd,backlog)<0)  {    err_sys("listen error");  }}void Connect(int sockfd,const struct sockaddr *servaddr, socklen_t addrlen){  if(connect(sockfd,servaddr,addrlen)<0)  {    err_sys("connect error");  }  else  {    printf("connect success!\n");  }}int Accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen){  int n;  again:    if ((n=accept(sockfd,cliaddr,addrlen))<0)    {#ifndef EPROTO      if(errno == EPROTO || errno == ECONNABORTED)#else      if(errno == ECONNABORTED)#endif      {          goto again;      }      else      {        err_sys("accept error");      }    }  return n;}ssize_t Writen(int fd,char *buf, size_t n){  ssize_t ret;  ret = writen(fd,buf,n);  if (ret < 0)  {    err_sys("writen error");    return -1;  }  return ret;}ssize_t Readline(int fd, void *vptr, size_t maxlen){  ssize_t n;  n=readline(fd,vptr,maxlen);  if (n<0)  {    err_sys("readline error");    return -1;  }  return n;}

4、客户端功能行函数:func.c

#include "unp.h"ssize_t writen(int fd, char *buf, size_t n){  size_t nleft;  ssize_t nwritten;  char *ptr;  ptr = buf;  nleft = n ;  while(nleft > 0)  {    nwritten = write(fd, ptr, nleft);    if (nwritten < 0 && errno == EINTR)    {      nwritten = 0;          }    else if (nwritten < 0)    {      err_sys("write error");      return -1;    }    nleft -= nwritten;    ptr += nwritten;  }  return n;}void str_echo(int sockfd){  ssize_t n;  char buf[MAXLINE];  again:    while ((n = read(sockfd, buf, MAXLINE))>0)      Writen(sockfd, buf, n);  if (n < 0 && errno == EINTR)  {    goto again;  }  else if (n < 0)  {    err_sys("str_echo error");  }}ssize_t readline(int fd, void *vptr, size_t maxlen){    ssize_t n,rc;    char c,*ptr;    ptr = vptr;    for (n = 1; n < maxlen; n++)    {        again:            if ((rc = read(fd, &c, 1)) == 1)            {                *ptr++ = c;                if (c == '\n')                {                    break;                }            }            else if (rc == 0)            {                *ptr = 0;                return (n-1);            }            else            {                if (errno == EINTR)                        {                    goto again;                }                return -1;            }    }    *ptr = 0;    return n;}void str_cli(FILE *fp, int sockfd){    char sendline[MAXLINE],recvline[MAXLINE];    bzero(sendline,sizeof(sendline));    bzero(recvline,sizeof(recvline));    while(fgets(sendline,MAXLINE,fp) != NULL)    {        Writen(sockfd,sendline,strlen(sendline));        if (Readline(sockfd, recvline, MAXLINE) == 0)        {            err_sys("str_cli Readline error");        }        fputs(recvline, stdout);    }}

5、客户端Makefile

clien:clien.o pack.o func.o    gcc clien.o pack.o func.o -o clienclien.o:clien.c unp.h     gcc -c clien.c -o clien.opack.o:pack.c unp.h     gcc -c pack.c -o pack.ofunc.o:func.c unp.h     gcc -c func.c -o func.o    .PHONY:cleanclean:    rm -f *.o

二:服务器程序

1、头文件:unp.h

#ifndef _unp_h#define _unp_h#include <sys/types.h> /* basic system data types */#include <sys/socket.h> /* basic socket definitions */#include <sys/time.h> /* timeval{} for select() */#include <time.h>  /* timespec{} for pselect() */#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */#include <arpa/inet.h> /* inet(3) functions */#include <errno.h>#include <fcntl.h>  /* for nonblocking */#include <netdb.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/stat.h> /* for S_xxx file mode constants */#include <sys/uio.h>  /* for iovec{} and readv/writev */#include <unistd.h>#include <sys/wait.h>#include <sys/un.h>  /* for Unix domain sockets */#define MAXLINE 4096#define LISTENQ 5#define SERV_PORT   9877typedef void (*sighandler_t)(int);sighandler_t Signal(int signum, sighandler_t handler);//signal函数的包裹函数int Socket(int sockfd, int type, int protocol);//socket的包裹函数void Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);//bind函数的包裹函数void Listen(int sockfd,int backlog);//listen函数的包裹函数void Connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);//connect函数的包裹函数int Accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);//accept函数的包裹函数void Write(int fd,void *buf,size_t count);//write函数的包裹函数void Close(int sockfd);//关闭套接字函数close的包裹函数void err_sys(char *err_str);//错误输出函数int Fork();//fork函数的包裹函数void str_echo(int sockfd);//回射函数ssize_t writen(int fd, char *buf, size_t n);//写n个字符的writen函数ssize_t Writen(int fd, char *buf, size_t n);//writen函数的包裹函数void sig_chlid(int signo);//信号控制函数sig_child#endif


2、服务器主程序:serv.c

#include "unp.h"void sig_chld(int );int main(int argc, char const *argv[]){    int listenfd,connfd;    pid_t childpid;    socklen_t clilen;    struct sockaddr_in cliaddr,servaddr;    listenfd = Socket(AF_INET, SOCK_STREAM, 0);//监听套接字创建    bzero(&servaddr, sizeof(servaddr));    servaddr.sin_family = AF_INET;//服务器地址族    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//服务器地址赋值,一般服务器地址不指定    servaddr.sin_port = htons(SERV_PORT);//服务器端口赋值    Bind(listenfd,(struct sockaddr*)&servaddr, sizeof(servaddr));//绑定监听套接字与服务器的端口    Listen(listenfd, LISTENQ);  //监听    Signal(SIGCHLD, sig_chld);  //回收僵死子进程    while(1)    {        clilen = sizeof(cliaddr);        connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);//accept创建已连接套接字connfd        if (connfd<0) {          if(errno == EINTR)//处理系统中断          {            continue;          }          else          {            err_sys("accept error");          }        }        if ((childpid = Fork()) == 0)//创建子进程        {            Close(listenfd);//子进程关闭监听套接字            str_echo(connfd);//调用回射函数            exit(0);        }        else//父进程        {            Close(connfd);//父进程关闭已连接套接字        }    }    return 0;}

3、包裹函数:pack.c

#include "unp.h"void err_sys(char *err_str){  perror(err_str);}int Socket(int sockfd, int type, int protocol){  int n=0;  if ((n=socket(sockfd,type,protocol))<0)  {    err_sys("socket error");  }  printf("socket success!sockfd=%d\n",n);  return n;}void Bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen){  int n=0;  if ((n = bind(sockfd,myaddr,addrlen))<0)  {    err_sys("bind error");  }  printf("bind success\n");}void Listen(int sockfd,int backlog){  char *ptr=NULL;  if ((ptr=getenv("LISTENQ"))!=NULL)  {    backlog=atoi(ptr);  }  if (listen(sockfd,backlog)<0)  {    err_sys("listen error");  }  printf("listen success\n");}void Connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen){  if(connect(sockfd,servaddr,addrlen)<0)  {    err_sys("connect error");  }  printf("connect success!\n");}int Accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen){  int n;  again:    if ((n=accept(sockfd,cliaddr,addrlen))<0)    {#ifndef EPROTO      if(errno == EPROTO || errno == ECONNABORTED)#else      if(errno == ECONNABORTED)#endif      {          goto again;      }      else      {        err_sys("accept error");      }    }  return n;}void Write(int fd,void *buf,size_t count){ssize_t n;n=write(fd,buf,count);if(n!=count){err_sys("write error");}}void Close(int sockfd){if(close(sockfd)==-1){err_sys("close error");    }}int Fork(){  pid_t pid;  if ((pid = fork()) < 0)  {    err_sys("fork error");  }  else    return pid;}ssize_t Writen(int fd,char *buf, size_t n){  ssize_t ret;  ret = writen(fd,buf,n);  if (ret < 0)  {    err_sys("writen error");    return -1;  }  return ret;}sighandler_t Signal(int signum, sighandler_t handler){  if (signal(signum, handler)==SIG_ERR)  {    err_sys("signal error");    exit(-1);  }  }

4、功能性函数:func.c

#include "unp.h"ssize_t writen(int fd, char *buf, size_t n){  size_t nleft;  ssize_t nwritten;  char *ptr;  ptr = buf;  nleft = n ;  while(nleft > 0)  {    nwritten = write(fd, ptr, nleft);    if (nwritten < 0 && errno == EINTR)    {      nwritten = 0;    }    else if (nwritten < 0)    {      err_sys("write error");      return -1;    }    nleft -= nwritten;    ptr += nwritten;  }  return n;}void str_echo(int sockfd){  ssize_t n;  char buf[MAXLINE];  again:    while ((n = read(sockfd, buf, MAXLINE))>0)      Writen(sockfd, buf, n);  if (n < 0 && errno == EINTR)  {    goto again;  }  else if (n < 0)  {    err_sys("str_echo error");  }}void sig_chld(int signum){    pid_t pid;    int stat;    while((pid = waitpid(-1, &stat, WNOHANG)) >0 )    {      printf("chlid %d terminated!\n",pid);    }    // pid = wait(&stat);    // printf("child %d terminated!\n", pid);    return ;}
5、服务器Makefile

serv:serv.o pack.o func.o    gcc serv.o pack.o func.o -o servserv.o:serv.c unp.h    gcc -c serv.c -o serv.opack.o:pack.c unp.h    gcc -c pack.c -o pack.ofunc.o:func.c unp.h    gcc -c func.c -o func.o.PHONY:cleanclean:    rm -f *.o




阅读全文
0 0
原创粉丝点击