- 1、流程
- 2、代码
- 3、socket常用函数出错处理封装
全局定义了一个结构体,成员为,客户端通信的文件描述符,和返回的客户端信息结构体 主线程: 创建结构体数组(存文件描述符、客户端信息结构体) 1、socket创建套接字 2、bind绑定ip端口号 3、listen 设置最大连接数 4、accpet阻塞等待客户端连接 连接成功之后间:用于通信的文件描述符存到结构体中 5、创建子线程,并把对应的结构体数组传递过去 6、设置线程分离(自动回收) 子线程: 1、read数据 2、将读到的数据转换成大写 3、回写给客户端 循环监听,知道read读到0表示客户端断开2、代码
#include3、socket常用函数出错处理封装#include #include #include #include #include #include #include "socket_wrap.h" #define MAXLINE 8192 #define SERV_PORT 9999 struct s_info { //定义一个结构体, 将地址结构跟cfd捆绑 struct sockaddr_in cliaddr; int connfd; }; void *do_work(void *arg) { int n,i; struct s_info *ts = (struct s_info*)arg; char buf[MAXLINE]; char str[INET_ADDRSTRLEN]; //#define INET_ADDRSTRLEN 16 可用"[+d"查看 while (1) { n = Read(ts->connfd, buf, MAXLINE); //读客户端 if (n == 0) { printf("the client %d closed...n", ts->connfd); break; //跳出循环,关闭cfd } printf("received from %s at PORT %dn", inet_ntop(AF_INET, &(*ts).cliaddr.sin_addr, str, sizeof(str)), ntohs((*ts).cliaddr.sin_port)); //打印客户端信息(IP/PORT) for (i = 0; i < n; i++) buf[i] = toupper(buf[i]); //小写-->大写 Write(STDOUT_FILENO, buf, n); //写出至屏幕 Write(ts->connfd, buf, n); //回写给客户端 } Close(ts->connfd); return (void *)0; } int main(void) { struct sockaddr_in servaddr, cliaddr; socklen_t cliaddr_len; int listenfd, connfd; pthread_t tid; struct s_info ts[256]; //创建结构体数组. int i = 0; listenfd = Socket(AF_INET, SOCK_STREAM, 0); //创建一个socket, 得到lfd bzero(&servaddr, sizeof(servaddr)); //地址结构清零 servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //指定本地任意IP servaddr.sin_port = htons(SERV_PORT); //指定端口号 Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); //绑定 Listen(listenfd, 128); //设置同一时刻链接服务器上限数 printf("Accepting client connect ...n"); while (1) { cliaddr_len = sizeof(cliaddr); connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); //阻塞监听客户端链接请求 ts[i].cliaddr = cliaddr; ts[i].connfd = connfd; pthread_create(&tid, NULL, do_work, (void*)&ts[i]); pthread_detach(tid); //子线程分离,防止僵线程产生. i++; } return 0; }
socket_wrap.h
#ifndef __WRAP_H_ #define __WRAP_H_ void perr_exit(const char* s); int Accept(int fd,struct sockaddr* sa,socklen_t* salenptr); int Bind(int fd,const struct sockaddr* sa,socklen_t salen); int Connect(int fd,const struct sockaddr* sa,socklen_t salen); int Listen(int fd,int backlog); int Socket(int family,int type,int protocol); ssize_t Read(int fd,void* ptr,size_t nbytes); ssize_t Write(int fd,const void* ptr,size_t nbytes); int Close(int fd); ssize_t Readn(int fd,void* vptr,size_t n); ssize_t Writen(int fd,const void* vptr,size_t n); static ssize_t my_read(int fd,char* ptr); ssize_t Readline(int fd,void* vptr,size_t maxlen); #endif // !__WRAP_H_
socket_wrap.c
#include#include #include #include #include #include #include #include #include #include "socket_wrap.h" void perr_exit(const char* s) { perror(s); exit(1); } int Accept(int fd,struct sockaddr* sa,socklen_t* salenptr) { int n; again: if((n=accept(fd,sa,salenptr))<0) { if(errno == EConNABORTED || (errno==EINTR)) goto again; else perr_exit("accept error"); } return n; } int Bind(int fd,const struct sockaddr* sa,socklen_t salen) { int n; if((n=bind(fd,sa,salen))<0) { perr_exit("bind error"); } return n; } int Connect(int fd,const struct sockaddr* sa,socklen_t salen) { int n; if((n=connect(fd,sa,salen))<0) perr_exit("connect error"); return n; } int Listen(int fd,int backlog) { int n; if((n=listen(fd,n))<0) { perr_exit("listen error"); } return n; } int Socket(int family,int type,int protocol) { int n; if((n=socket(family,type,protocol))<0) perr_exit("socket error"); return n; } ssize_t Read(int fd,void* ptr,size_t nbytes) { ssize_t n; again: if((n=read(fd,ptr,nbytes))<0) { if(errno==EINTR) goto again; else return -1; } return n; } ssize_t Write(int fd,const void* ptr,size_t nbytes) { ssize_t n; if((n=write(fd,ptr,nbytes))<0) perr_exit("write error"); return n; } int Close(int fd) { int n; if((n=close(fd))<0) perr_exit("close error"); return n; } ssize_t Readn(int fd,void* vptr,size_t n) { size_t nleft; // unsigned int 剩余未读取字节数 ssize_t nread; // int 实际读到的字节数 char* ptr; ptr = vptr; nleft = n; while (nleft>0) { if((nread = read(fd,ptr,nleft))<0) { if(errno == EINTR) nread = 0; else return -1; } else if(nread == 0) break; nleft -= nread; ptr+=nread; } return n-nread; } ssize_t 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; else return -1; } nleft -= nwritten; ptr += nwritten; } return n; } static ssize_t my_read(int fd,char* ptr) { static int read_cnt; static char* read_ptr; static char read_buf[100]; if(read_cnt<=0) { again: if((read_cnt=read(fd,read_buf,sizeof(read_buf)))<0) { if(errno == EINTR) goto again; return -1; } else if(read_cnt == 0) return 0; read_ptr = read_buf; } read_cnt--; *ptr = *read_ptr++; return 1; } // 传出参数 vptr ssize_t Readline(int fd,void* vptr,size_t maxlen) { ssize_t n,rc; char c,*ptr; ptr = vptr; for(n=1;n



