首页 > 代码库 > Socket编程实践(20) --Socket API封装(3)
Socket编程实践(20) --Socket API封装(3)
注:这一片博客与上一篇博客<Socket编程实践(19)>合为一篇,由于代码较多,所以分为两篇,本篇为下篇,这一篇主要讲解怎样使用上一篇开发的增强版的Socket类(ServerSocket/ClientSocket类的实现与使用)!
思想来源:
1)http://www.cnblogs.com/-Lei/archive/2012/09/04/2670964.html
2)http://blog.csdn.net/column/details/linux66.html
3)http://blog.csdn.net/column/details/zjf666.html
亮点内容:
1)添加了异常处理(在ServerSocket/ClientSocket继承父类Socket的同时,也处理了父类函数调用可能出现的错误,并throw出来,由使用这两个类的代码进行处理),让我们在编写易出错的代码时,可以解放思想,不用一直考虑该函数调用出错会发生什么情况!
2)SeverSocket/ClientSocket类重写覆盖了父类Socket的Send/Receive成员函数,使得这两个函数更加易用(从client端的代码中可看出)
3)在Server端代码中,遵循Peer Connect one Process, 添加了fork调用,每一个子进程处理一个连接
4)在Server端添加了捕获SIGCHLD的代码,防止出现僵尸进程.
5)在Server/Client端代码中添加try/catch语句,处理出错情况.
ServerSocket类
//In ServerSocket.h #ifndef SERVERSOCKET_H_INCLUDED #define SERVERSOCKET_H_INCLUDED #include "Socket.h" #include "SocketException.h" class ServerSocket : public Socket { public: ServerSocket(int port, int backlog = SOMAXCONN); virtual ~ServerSocket(); void Accept(Socket &clientSocket) const; /**Over write the Send & Receive**/ size_t Send(const Socket& socket, const std::string& message) const; size_t Receive(const Socket& socket, std::string& message) const; }; #endif // SERVERSOCKET_H_INCLUDED
//In ServerSocket.cpp #include "ServerSocket.h" ServerSocket::ServerSocket(int port, int backlog) { if (!Socket::Create()) { throw SocketException("Create server socket error"); } if (!Socket::Bind(port)) { throw SocketException("Sever socket bind a port error"); } if (!Socket::Listen(backlog)) { throw SocketException("Server socket listen error"); } } ServerSocket::~ServerSocket() { } void ServerSocket::Accept(Socket &clientSocket) const { if (!Socket::Accept(clientSocket)) { throw SocketException("Accept a connect error"); } } size_t ServerSocket::Send(const Socket &socket, const std::string &message) const { size_t nSend = Socket::Send(socket,message); if (nSend < 0) { throw SocketException("Send messages error"); } return nSend; } size_t ServerSocket::Receive(const Socket &socket, std::string &message) const { size_t nRead = Socket::Receive(socket,message); if (nRead == 0) { throw SocketException("Peer connect closed"); } else if (nRead < 0) { throw SocketException("Receive messages error"); } return nRead; }
ClientSocket类
//In ClientSocket.h #ifndef CLIENTSOCKET_H_INCLUDED #define CLIENTSOCKET_H_INCLUDED #include "Socket.h" #include "SocketException.h" class ClientSocket : public Socket { public: ClientSocket(const std::string &serverHost, int port); ~ClientSocket(); size_t Send(const std::string& message) const; size_t Receive(std::string& message) const; }; #endif // CLIENTSOCKET_H_INCLUDED
//In ClientSocket.cpp #include "ClientSocket.h" ClientSocket::ClientSocket(const std::string &serverHost, int port) { if (!Socket::Create()) { throw SocketException("Create client socket error"); } if (!Socket::Connect(serverHost,port)) { throw SocketException("Connect server socket error"); } } ClientSocket::~ClientSocket() { } size_t ClientSocket::Send(const std::string &message) const { size_t nSend = Socket::Send(static_cast<const Socket&>(*this),message); if (nSend < 0) { throw SocketException("Send messages error"); } return nSend; } size_t ClientSocket::Receive(std::string &message) const { size_t nRead = Socket::Receive(static_cast<const Socket&>(*this),message); if (nRead == 0) { throw SocketException("Peer connect closed"); } else if (nRead < 0) { throw SocketException("Receive messages error"); } return nRead; }
Server端 and Client端完整代码
//server.cpp #include "ServerSocket.h" #include "SocketException.h" #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <signal.h> #include <iostream> using namespace std; void onSigChild(int signalNumber) { if (signalNumber == SIGCHLD) { while (wait(NULL) != -1) ; } } int main() { signal(SIGCHLD,onSigChild); cout << "Server Running..." << endl; try { ServerSocket server(9001); while (true) { Socket newSocket; server.Accept(newSocket); cout << "Client information:" << endl; cout << ‘\t‘ << newSocket.getAddr() << endl; cout << ‘\t‘ << newSocket.getPort() << endl; pid_t pid = fork(); if (pid == -1) { perror("fork error"); } else if (pid == 0) { server.Close(); while (true) { try { string messages; server.Receive(newSocket,messages); cout << messages << endl; server.Send(newSocket,messages); } catch (SocketException &ex) { cerr << ex.Description() << endl; exit(0); } } } else { newSocket.Close(); } } } catch (SocketException &ex) { cerr << ex.Description() << endl; } return 0; }
//client.cpp #include <iostream> #include <string> #include "ClientSocket.h" #include "SocketException.h" using namespace std; int main() { cout<<"Running client...."<<endl; try { ClientSocket clientSocket("127.0.0.1",9001); try { string messages; while (getline(cin,messages)) { if (messages.length() == 0) { messages.append("\n"); } clientSocket.Send(messages); messages.clear(); clientSocket.Receive(messages); cout << messages << endl; } } catch (SocketException &ex) { cerr << ex.Description() << endl; } } catch (SocketException &ex) { cerr << ex.Description() << endl; } return 0; }
运行截图:
附-Makefile
CC = g++ CPPFLAGS = -Wall -g -pthread BIN = server client SOURCES = $(BIN.=.cpp) .PHONY: clean all all: $(BIN) $(BIN): $(SOURCES) Socket.cpp ServerSocket.cpp ClientSocket.cpp clean: -rm -rf $(BIN) bin/ obj/ core
Socket编程实践(20) --Socket API封装(3)