首页 > 代码库 > Socket编程实践(18) --Socket API 封装(1)
Socket编程实践(18) --Socket API 封装(1)
序言:
定义一套用于TCP通信比较实用/好用Socket类库(运用C++封装的思想,将socket API尽量封装的好用,实用);
思想来源:http://www.cnblogs.com/-Lei/archive/2012/09/04/2670942.html
Socket.h
#ifndef SOCKET_H_INCLUDED #define SOCKET_H_INCLUDED #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string> #include <string.h> #include <fcntl.h> class Socket { public: Socket(); virtual ~Socket(); //virtual destructior bool Create(); //Create a socket, server & client can use /**Server**/ bool Bind(int port) const; //Bind a port bool Listen(int backlog = SOMAXCONN) const; //Start to listen bool Accept(Socket& clientSocket) const; //Accept a connect /**Client**/ bool Connect(const std::string& host, int port); /** Data Transmission: return=0: write or read nothing (if receive == 0,peer connect closed) return<0: write error(errno is set) return>0: write success(return value is the bytes have send/receive) **/ size_t Send(const Socket& socket, const std::string& message) const; size_t Receive(const Socket& socket, std::string& message) const; /***All can Use!***/ //flag: true=SetNonBlock, false=SetBlock bool SetNonBlocking(bool flag); //return: true -> SetSuccess bool SetReuseAddr(); //test for m_sockfd; bool IsValid() const; private: //use m_sockfd to record the result of function socket int m_sockfd; struct sockaddr_in m_address; //define the max bytes to send/write static const int BUFSIZ = 1024*10; }; #endif // SOCKET_H_INCLUDED
Socket.cpp
#include "Socket.h" Socket::Socket():m_sockfd(-1) { } Socket::~Socket() { if (IsValid()) { close(m_sockfd); } } bool Socket::Create() { m_sockfd = socket(AF_INET,SOCK_STREAM,0); if (IsValid()) return true; return false; } //bind a server port at the server bool Socket::Bind(int port) const { if (!IsValid()) { return false; } struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(port); serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(m_sockfd,(const struct sockaddr *)&serverAddr, sizeof(struct sockaddr)) == -1) { return false; } return true; } bool Socket::Listen(int backlog) const { if (!IsValid()) { return false; } if (listen(m_sockfd,backlog) == -1) { return false; } return true; } bool Socket::Accept(Socket &clientSocket) const { if (!IsValid()) { return false; } socklen_t clientAddrLength = sizeof(clientSocket.m_address); clientSocket.m_sockfd = accept(m_sockfd, (struct sockaddr *)(&clientSocket.m_address), &clientAddrLength); if (clientSocket.m_sockfd == -1) { return false; } return true; } //Client bool Socket::Connect(const std::string &serverHost, int serverPort) { if (!IsValid()) { return false; } struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = inet_addr(serverHost.c_str()); serverAddr.sin_port = htons(serverPort); if (connect(m_sockfd,(const struct sockaddr *)(&serverAddr), sizeof(struct sockaddr)) == -1) { return false; } return true; } size_t Socket::Send(const Socket &peerSocket, const std::string &messages) const { struct TransStruct { size_t bufLen; //保存真实的报文内容长度 char buf[BUFSIZ]; //真正要发送的报文内容 } sendStruct; sendStruct.bufLen = messages.length(); strncpy(sendStruct.buf,messages.c_str(),sendStruct.bufLen); ssize_t nWrited = write(peerSocket.m_sockfd,&sendStruct, sendStruct.bufLen+sizeof(size_t)); if (nWrited == 0) { return 0; } else if (nWrited == -1) { return -1; } return nWrited; } size_t Socket::Receive(const Socket &peerSocket, std::string &messages) const { size_t messageLen = 0; if (read(peerSocket.m_sockfd,&messageLen,sizeof(size_t)) == -1) { return false; } char buf[BUFSIZ]; memset(buf,0,sizeof(buf)); messages.clear(); ssize_t nRead = read(peerSocket.m_sockfd,buf,messageLen); if (nRead == 0) { return 0; } else if (nRead == -1) { return -1; } messages = buf; return nRead; } //Set the sockfd NonBlocked bool Socket::SetNonBlocking(bool flag) { if (IsValid()) { int opts = fcntl(m_sockfd,F_GETFL); if (opts == -1) { return false; } if (flag) { opts |= O_NONBLOCK; } else { opts &= ~O_NONBLOCK; } return fcntl(m_sockfd,F_SETFL,opts); } return false; } //Set the address Reused bool Socket::SetReuseAddr() { if (IsValid()) { int on = 1; if (setsockopt(m_sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) == -1) { return false; } else { return true; } } return false; } bool Socket::IsValid() const { //If m_sockfd is not Call Create, m_sockfd == -1 //Else m_sockfd != -1 return m_sockfd != -1; }
测试:一个简陋的echo回声server/client
//server端 #include "comment.h" int main() { Socket serverSocket; if (!serverSocket.Create()) { err_exit("create error"); } if (!serverSocket.Bind(9001)) { err_exit("bind error"); } if (!serverSocket.Listen()) { err_exit("listen error"); } Socket clientSocket; if (!serverSocket.Accept(clientSocket)) { err_exit("accept error"); } string message; while (true) { int recvCount = serverSocket.Receive(clientSocket,message); if (recvCount == -1) { err_exit("receive error"); } else if (recvCount == 0) { cerr << "client connect closed!" << endl; exit(0); } cout << message << endl; if (!serverSocket.Send(clientSocket,message)) { err_exit("send error"); } } return 0; }
//client端 #include "comment.h" int main() { Socket clientSocket; if (!clientSocket.Create()) { err_exit("create error"); } if (!clientSocket.Connect("127.0.0.1",9001)) { err_exit("connect error"); } string sendBuf; while (getline(cin,sendBuf)) { if (!clientSocket.Send(clientSocket,sendBuf)) { err_exit("send error"); } sendBuf.clear(); if (!clientSocket.Receive(clientSocket,sendBuf)) { err_exit("receive error"); } cout << sendBuf << endl; } return 0; }
附-commen.h
#ifndef COMMENT_H_INCLUDED #define COMMENT_H_INCLUDED #include "Socket.h" #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <iostream> using namespace std; inline void err_exit(std::string args) { perror(args.c_str()); _exit(EXIT_FAILURE); } #endif // COMMENT_H_INCLUDED
附-Makefile
CC = g++ CPPFLAGS = -Wall -g -pthread BIN = server client SOURCES = $(BIN.=.cpp) .PHONY: clean all all: $(BIN) $(BIN): $(SOURCES) Socket.cpp clean: -rm -rf $(BIN) bin/ obj/ core
Socket编程实践(18) --Socket API 封装(1)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。