本文主要给大家提供一个Tcp Server的源码例子,各源码所在的文件名已在注释中标出。
C++代码
- //Filename: SockClass.cpp
- #include "SockClass.hpp"
- //sockClass
- namespace sockClass
- {
- void error_info(const char* s)
- {
- std::cerr << s << std::endl;
- throw WSAGetLastError();
- }
- }
- //class WinsockAPI
- WinsockAPI::WinsockAPI(int low_byte, int high_byte)
- {
- const WORD wVersionRequested = MAKEWORD(low_byte, high_byte);
- int wsa_startup_err = WSAStartup(wVersionRequested, &wsaData);
- if (wsa_startup_err != 0) {
- std::cerr << "WSAStartup() failed." << std::endl;
- throw wsa_startup_err;
- }
- }
- WinsockAPI::~WinsockAPI()
- {
- WSACleanup();
- }
- void WinsockAPI::showVersion() const
- {
- std::cout << "The version of Winsock.dll is "
- << int(LOBYTE(wsaData.wVersion))
- << "."
- << int(HIBYTE(wsaData.wVersion))
- << "."
- << std::endl;
- return;
- }
- //class BaseSock
- BaseSock::BaseSock():
- sockFD(-1)
- {}
- BaseSock::~BaseSock()
- {}
- const int& BaseSock::showSockFD() const
- {
- return sockFD;
- }
- //class TCPListenSock
- TCPListenSock::TCPListenSock(unsigned short listen_port)
- {
- sockFD = socket(PF_INET,
- SOCK_STREAM,
- IPPROTO_TCP);
- if (sockFD < 0) {
- sockClass::error_info("socket() failed.");
- }
- memset(&listenSockAddr, 0, sizeof(listenSockAddr));
- listenSockAddr.sin_family = AF_INET;
- listenSockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
- listenSockAddr.sin_port = htons(listen_port);
- if (bind( sockFD,
- (sockaddr*)&listenSockAddr,
- sizeof(listenSockAddr)) < 0) {
- sockClass::error_info("bind() failed.");
- }
- }
- TCPListenSock::~TCPListenSock()
- {
- closesocket(sockFD);
- }
- void TCPListenSock::TCPListen(
- int max_connection_requests) const
- {
- if (listen( sockFD,
- max_connection_requests) < 0) {
- sockClass::error_info("listen() failed.");
- }
- }
- //class TCPServerSock
- TCPServerSock::TCPServerSock(
- const TCPListenSock& listen_sock,
- int pre_buffer_size):
- preBufferSize(pre_buffer_size),
- preReceivedLength(0)
- {
- preBuffer = new char[preBufferSize];
- int clientSockAddrLen = sizeof(clientSockAddr);
- sockFD = accept( listen_sock.showSockFD(),
- (sockaddr*)&clientSockAddr,
- &clientSockAddrLen);
- if (sockFD < 0) {
- sockClass::error_info("accept() failed.");
- }
- std::cout << "Client (IP: "
- << inet_ntoa(clientSockAddr.sin_addr)
- << ") conneted." << std::endl;
- }
- TCPServerSock::~TCPServerSock()
- {
- delete [] preBuffer;
- closesocket(sockFD);
- }
- int TCPServerSock::TCPReceive() const
- {
- preReceivedLength = recv( sockFD,
- preBuffer,
- preBufferSize,
- 0);
- if (preReceivedLength < 0) {
- sockClass::error_info("recv() failed.");
- } else if (preReceivedLength == 0) {
- std::cout << "Client has been disconnected.\n";
- return 0;
- }
- return preReceivedLength;
- }
- int TCPServerSock::TCPSend(const char* send_data,
- const int& data_length) const
- {
- if (data_length > preBufferSize) {
- throw "Data is too large, resize preBufferSize.";
- }
- int sent_length = send( sockFD,
- send_data,
- data_length,
- 0);
- if (sent_length < 0) {
- sockClass::error_info("send() failed.");
- } else if (sent_length != data_length) {
- sockClass::error_info("sent unexpected number of bytes.");
- }
- return sent_length;
- }
C++代码
- //Filename: SockClass.hpp
- #ifndef SOCK_CLASS_HPP
- #define SOCK_CLASS_HPP
- #include <iostream>
- #include <winsock2.h>
- namespace sockClass
- {
- void error_info(const char* s);
- }
- class WinsockAPI{
- private:
- WSADATA wsaData;
- public:
- WinsockAPI(int low_byte = 2, int high_byte = 2);
- ~WinsockAPI();
- void showVersion() const;
- };
- class BaseSock{
- protected:
- int sockFD;
- public:
- BaseSock();
- virtual ~BaseSock() = 0;
- const int& showSockFD() const;
- };
- class TCPListenSock: public BaseSock{
- private:
- sockaddr_in listenSockAddr;
- public:
- TCPListenSock(unsigned short listen_port);
- ~TCPListenSock();
- void TCPListen(
- int max_connection_requests = 10) const;
- };
- class TCPServerSock: public BaseSock{
- private:
- sockaddr_in clientSockAddr;
- protected:
- char* preBuffer;
- int preBufferSize;
- mutable int preReceivedLength;
- public:
- TCPServerSock(
- const TCPListenSock& listen_sock,
- int pre_buffer_size = 32);
- virtual ~TCPServerSock();
- int TCPReceive() const;
- int TCPSend(const char* send_data,
- const int& data_length) const;
- };
- #endif //SockClass.hpp
C++代码
- //Filename: AppSock.cpp
- #include <string>
- #include "AppSock.hpp"
- TCPEchoServer::TCPEchoServer(const TCPListenSock& listen_sock, int pre_buffer_size):
- TCPServerSock(listen_sock, pre_buffer_size)
- {}
- TCPEchoServer::~TCPEchoServer()
- {}
- bool TCPEchoServer::handEcho() const
- {
- const std::string SHUTDOWN_CMD = "/shutdown";
- while (TCPReceive() > 0) {
- std::string cmd(preBuffer, SHUTDOWN_CMD.size());
- if (cmd == SHUTDOWN_CMD && preReceivedLength == SHUTDOWN_CMD.size()) {
- return false;
- }
- TCPSend(preBuffer, preReceivedLength);
- }
- return true;
- }
C++代码
- //Filename AppSock.hpp
- #ifndef APP_SOCK_HPP
- #define APP_SOCK_HPP
- #include "SockClass.hpp"
- class TCPEchoServer: public TCPServerSock{
- public:
- TCPEchoServer(
- const TCPListenSock& listen_sock,
- int pre_buffer_size = 32);
- ~TCPEchoServer();
- bool handEcho() const;
- };
- #endif //AppSock.hpp
C++代码
- //Filename: main.cpp
- #include "SockClass.hpp"
- #include "AppSock.hpp"
- int TCP_echo_server(int argc, char* argv[]);
- int main(int argc, char* argv[])
- {
- int mainRtn = 0;
- try {
- mainRtn =TCP_echo_server(argc, argv);
- }
- catch (const char* s) {
- perror(s);
- return 1;
- }
- catch (const int& err) {
- std::cerr << "Error: " << err << std::endl;
- return 1;
- }
- return mainRtn;
- }
- int TCP_echo_server(int argc, char* argv[])
- {
- const unsigned short DEFAULT_PORT = 5000;
- unsigned short listen_port = DEFAULT_PORT;
- if (argc == 2 && atoi(argv[1]) > 0) {
- listen_port = atoi(argv[1]);
- }
- WinsockAPI winsockInfo;
- winsockInfo.showVersion();
- TCPListenSock listen_sock(listen_port);
- listen_sock.TCPListen();
- bool go_on = true;
- while (go_on){
- TCPEchoServer echo_server(listen_sock);
- go_on = echo_server.handEcho();
- }
- return 0;
- }
除非特别注明,鸡啄米文章均为原创
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。