学习 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);#endif2、客户端主程序: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
- 学习 UNIX网络编程卷1:套接字 笔记1-实现一个简单的回射客户服务器程序
- UNIX网络编程卷1:套接字联网-第5章:TCP客户/服务器程序示例
- Unix网络编程 卷1 第8章:基本UDP套接字编程(UDP回射客户/服务器程序: main/dg_echo/dg_cli)
- 《UNIX网络编程 卷1》 笔记: TCP 客户/服务器程序示例
- UNIX网络编程卷1 回射客户程序 TCP客户程序设计范式
- 学习《UNIX网络编程 卷1:套接字联网API》
- 《UNIX网络编程 卷1》 笔记: 原始套接字—ping程序
- 《Unix网络编程卷1-套接字联网API》linux 学习笔记一
- UNIX网络编程卷1 回射客户程序 UDP 超时设置
- 《UNIX网络编程 卷1》 笔记: 使用select函数的单进程TCP回射服务器程序
- 《UNIX网络编程 卷1》 笔记: 使用poll函数的单进程TCP回射服务器程序
- 《UNIX网络编程 卷1》 笔记: 非阻塞式connect—web客户程序
- 《UNIX网络编程 卷1》 笔记: 多线程—web客户程序
- UNIX网络编程卷一 笔记 第五章 TCP客户/服务器程序示例
- UNIX 网络编程 卷一:套接字联网API(第3版) 读书笔记(5) 第五章 TCP客户/服务器程序示例
- 《UNIX网络编程 卷1》 笔记: 基本UDP套接字编程
- UNIX网络编程 卷1:套接字联网API
- UNIX网络编程卷1:套接字联网API
- SpringMVC接收列表数据集合或表格数据集合写法
- 恐惧:中年程序员会害怕丢掉工作吗?
- LeetCode-19. Remove Nth Node From End of List
- 微信公众平台获取网页授权(测试号)
- js 计时器,倒计时完整实例代码附效果图 制作一个当前时间的动态时钟
- 学习 UNIX网络编程卷1:套接字 笔记1-实现一个简单的回射客户服务器程序
- Java 根据指定日期计算所在周的周一和周日
- scala-high_order_function
- CentOS 6.7使用阿里云CentOS的yum源
- 生成器generator
- Determining IP information for eth1... failed; no link present. Check cable?解决
- ES6-正则的扩展-RegExp构造函数
- GitHub Desktop 百度云分享
- [Spark--版本更新]-----2.1.2发行说明