首页 > 代码库 > 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)