Preface:
Define a set for TCP communication more practical/easy to use Socket class library (using the idea of C + + packaging, the socket API as far as possible to encapsulate the useful, practical);
Source of thought: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:WR ITE error (errno is set) Return>0:write success (return value is the bytes has send/receive) **/size_t Se nd (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 the 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 Serverbool 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; Clientbool 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; Save the true message content length char buf[bufsiz]; The message content that is really to be sent} 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 nonblockedbool 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 Reusedbool 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 isn't call Create, M_SOCKFD = =-1//else m_sockfd! =-1 return M_SOC KFD! =-1;}
test : A rudimentary echo echo server/client
//server End # 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-side # 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;}
Attached -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
Attached -makefile
CC = g++ Cppflags =-wall-g-pthreadbin = Server Clientsources = $ (bin.=.cpp). Phony:clean All: $ (BIN) $ (BIN): $ (SOURCES) Socket.cppclean: -rm-rf $ (BIN) Bin/obj/core
Socket Programming Practice (--socket) API Encapsulation (1)