序言:
定义一套用于TCP通信比较实用/好用Socket类库(运用C++封装的思想,将socket API尽量封装的好用,实用);
思想来源:http://www.cnblogs.com/-Lei/archive/2012/09/04/2670942.html
#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#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;
}//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/ coreSocket编程实践(18) --Socket API 封装(1)
原文地址:http://blog.csdn.net/zjf280441589/article/details/41891183