C++封装socket
来源:互联网 发布:只有我知 在线观看 编辑:程序博客网 时间:2024/06/05 06:16
简单的封装socket,只提供基本的功能,以后慢慢扩展socket设置的功能;封装仅限于socket创建、绑定、侦听、连接和接受等功能,并返回socket fd,至于如何处理fd,可以交给事件驱动框架(以后慢慢弄起来,epoll或者pthread)。下面的代码就是使用封装的socket类,来创建一个echo server的服务器端和客户端,为了简单师范socket的类的使用,所以客户端输入终止符或者断开之后,服务器端也会终止。
static int SocketRead(int fd, char *buf, int count) { int nread, totlen = 0; while (totlen != count) { nread = read(fd, buf, count - totlen); if (0 == nread) return totlen; if (-1 == nread) return -1; totlen += nread; buf += nread; } return totlen;}static int SocketWrite(int fd, char *buf, int count) { int nwritten, totlen = 0; while (totlen != count) { nwritten = write(fd,buf,count - totlen); if (0 == nwritten) return totlen; if (-1 == nwritten) return -1; totlen += nwritten; buf += nwritten; } return totlen;}static int SocketCall (const char *label, int result) { if (-1 == result) { fprintf(stderr, "socket %s: %s\n", label, strerror(result)); } return result;}class MrSocket { public: MrSocket() : listen_fd_(-1) , connect_fd_(-1), client_fd_(-1) { } ~MrSocket() { if (listen_fd_ >= 0) { close(listen_fd_); } if (client_fd_ >= 0) { close(client_fd_); } if (connect_fd_ >= 0) { close(connect_fd_); } } int TcpServer(int port, char *bindaddr) { int s; struct sockaddr_in sa; if((s = Create(AF_INET)) == -1) { return -1; } // fill the socket addr memset(&sa,0,sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(port); sa.sin_addr.s_addr = htonl(INADDR_ANY); // TO DO: // if (bindaddr && (inet_aton(bindaddr,&SA.sin_addr) == 0)) ... close(s), return -1; if (-1 == Listen(s, (struct sockaddr *)&sa, sizeof(sa))) { return -1; } listen_fd_ = s; return s; } int Accpet(int listen_fd, struct sockaddr *cliaddr, socklen_t *clilen) { for ( ; ; ) { // Right now I am not fun of clent addr info // TO DO : add clent addr info processing if ((connect_fd_ = accept(listen_fd_,NULL,NULL)) < 0) { if (EINTR == errno) { fprintf(stderr, "restart sys api func\n"); continue; } else { fprintf(stderr, "accept: %s", strerror(errno)); return -1; } } break; } return connect_fd_; } int TcpClient(int port, char *servaddr) { int s; struct sockaddr_in sa; if((s = Create(AF_INET)) == -1) { return -1; } // TO DO: // use getaddrinfo to get the server's address info // and loop query the servinfo and connect to the valid one // see redis::anet.c::anetTcpGenericConnect(...) // fill the socket addr memset(&sa,0,sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(port); if (0 == SocketCall("inet_pton", inet_pton(AF_INET, servaddr, &sa.sin_addr))) { close(s); return -1; } if (-1 == SocketCall("connect", connect(s,(struct sockaddr*)&sa,sizeof(struct sockaddr_in)))) { close(s); return -1; } client_fd_ = s; return s; } int GetListenFd() { return listen_fd_; } int GetClientFd() { return client_fd_; } int GetConnectFd() { return connect_fd_; } private: int Create (int domain) { int s; if ((s = SocketCall("create socket", socket(domain, SOCK_STREAM, 0))) == -1) { return -1; } // TO DO: // if (SocketCall(set socket opt", setsocketopt(...)) == -1) ... return -1; return s; } int Listen (int s, struct sockaddr *sa, socklen_t len) { if (SocketCall("bind", bind(s,sa,len)) == -1) { close(s); return -1; } // Use a backlog of 512 entries. We pass 511 to the listen() call for // the kernel does: backlogsize = round_pow_of_two(backlogsize + 1); // which will thus give us a backlog of 512 entries if (SocketCall("listen", listen(s,511)) == -1) { close(s); return -1; } return 1; } private: int listen_fd_; int client_fd_; int connect_fd_;};
服务器端
int main() { MrSocket m_; m_.TcpServer(8700,NULL); std::cout<<"listen fd = "<<m_.GetListenFd()<<std::endl; int fd = m_.Accpet(m_.GetListenFd(),NULL,NULL); char recv_line[100] = {'\0'}; printf("accpet %d \n",m_.GetListenFd()); while (SocketRead(fd,recv_line,20)) { printf("read from client %d %s \n",fd,recv_line); SocketWrite(m_.GetConnectFd(), recv_line, 20); printf("echo %s back to client\n", recv_line, 20); } return 0;}
客户端
int main() { MrSocket m_; char ip[] = "127.0.0.1"; m_.TcpClient(8700,ip); char send_line[100] = {'\0'}; char recv_line[100] = {'\0'}; char *in; while (read(STDIN_FILENO,send_line,20)) { send_line[strlen(send_line)-1] = '\0'; printf("being to send: %s\n", send_line); SocketWrite(m_.GetClientFd(), send_line, 20); printf("send %s to server\n", send_line); SocketRead(m_.GetClientFd(), recv_line, 20); printf("frome server: %s\n",recv_line); } return 0;}
运行示例
[macduan@localhost socket]$ ./server listen fd = 3^Z[1]+ Stopped ./server[macduan@localhost socket]$ ps PID TTY TIME CMD 8139 pts/3 00:00:00 bash11388 pts/3 00:00:00 server11389 pts/3 00:00:00 ps[macduan@localhost socket]$ ./clientmacbeing to send: macsend mac to serverduan^C[macduan@localhost socket]$ ps PID TTY TIME CMD 8139 pts/3 00:00:00 bash11388 pts/3 00:00:00 server11392 pts/3 00:00:00 ps[macduan@localhost socket]$ fg./serveraccpet 3 read from client 4 mac echo mac back to client[macduan@localhost socket]$ ./server &[1] 11398[macduan@localhost socket]$ listen fd = 3[macduan@localhost socket]$ ./clientaccpet 3 macbeing to send: macsend mac to serverread from client 4 mac echo mac back to clientfrome server: mac[1]+ Done ./server[macduan@localhost socket]$ ps PID TTY TIME CMD 8139 pts/3 00:00:00 bash11401 pts/3 00:00:00 ps
0 0
- Socket封装
- C语言的socket封装库-waisock编程简介
- 自己封装socket
- 事件模型SOCKET封装
- Socket封装2
- Socket封装3
- Socket封装4
- Socket封装5
- Socket封装6
- Socket封装7
- Socket封装7
- Socket封装8
- Socket封装9
- Socket封装10
- Socket封装11
- Socket封装12
- 跨平台Socket封装
- 跨平台Socket封装
- jquery 一些选择器使用方法
- 如何在 SSAS服务器之间做同步
- div+css兼容性问题
- Tomcat 部署常见问题
- JavaSE 线程同步之synchronized
- C++封装socket
- do while(0)的另一个用途:消除goto语句。
- jQuery实现的全选、反选和不选功能
- ubuntu 13.10 eclipse 汉化
- C++11之decltype
- cglib 动态代理
- ZOJ 3640 Help Me Escape(概率dp)
- 排序(三) 堆排序
- 关于坚持