实例:linux下实现简单的socket 客户端 服务端

原理不再赘述

文件构成:

client.cpp
client_socket.cpp
client_socket.h
Makefile
server.cpp
server_socket.cpp
server_socket.h
socket.cpp
socket_exception.h
socket.h

1.socket.h文件 主要实现基类

#ifndef SOCKET_H
#define SOCKET_H


#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <string>
#include <arpa/inet.h>


const int MAXHOSTNAME = 200;
const int MAXCONNECTIONS = 5;
const int MAXRECV = 500;

class Socket
{
public:
    Socket();
    virtual ~Socket();

    // Server initialization
    bool create();
    bool bind ( const int port );
    bool listen() const;
    bool accept ( Socket& ) const;

    // Client initialization
    bool connect ( const std::string host, const int port );

    // Data Transimission
    bool send ( const std::string ) const;
    int recv ( std::string& ) const;


    void set_non_blocking ( const bool );

    bool is_valid() const
    {
        return m_sock != -1;
    }

private:

    int m_sock;
    sockaddr_in m_addr;


};
2.socket.cpp

#include "socket.h"
#include <iostream>
#include <string>
#include <errno.h>
#include <fcntl.h>
#include <memory.h>
using namespace std;



Socket::Socket() : m_sock ( -1 )
{

    memset ( &m_addr, 0, sizeof ( m_addr ) );

}

Socket::~Socket()
{
    if ( is_valid() )::close ( m_sock );
}

bool Socket::create()
{
    m_sock = socket ( AF_INET, SOCK_STREAM, 0 );

    if ( ! is_valid() )
        return false;


    // TIME_WAIT - argh
    int on = 1;
    if ( setsockopt ( m_sock, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof ( on ) ) == -1 )
        return false;


    return true;

}
bool Socket::bind ( const int port )
{

    if ( ! is_valid() )
    {
        return false;
    }



    m_addr.sin_family = AF_INET;
    m_addr.sin_addr.s_addr = INADDR_ANY;
    m_addr.sin_port = htons ( port );

    int bind_return = ::bind ( m_sock, ( struct sockaddr * ) &m_addr, sizeof ( m_addr ) );


    if ( bind_return == -1 )
    {
        return false;
    }

    return true;
}


bool Socket::listen() const
{
    if ( ! is_valid() )
    {
        return false;
    }

    int listen_return = ::listen ( m_sock, MAXCONNECTIONS );


    if ( listen_return == -1 )
    {
        return false;
    }

    return true;
}

bool Socket::accept ( Socket& new_socket ) const
{
    int addr_length = sizeof ( m_addr );
    new_socket.m_sock = ::accept ( m_sock, ( sockaddr * ) &m_addr, ( socklen_t * ) &addr_length );

    if ( new_socket.m_sock <= 0 )
        return false;
    else
        return true;
}


bool Socket::send ( const std::string s ) const
{
    int status = ::send ( m_sock, s.c_str(), s.size(), MSG_NOSIGNAL );
    if ( status == -1 )
    {
        return false;
    }
    else
    {
        return true;
    }
}
int Socket::recv ( std::string& s ) const
{
    char buf [ MAXRECV + 1 ];

    s = "";

    memset ( buf, 0, MAXRECV + 1 );

    int status = ::recv ( m_sock, buf, MAXRECV, 0 );

    if ( status == -1 )
    {
        cout << "status == -1   errno == " << errno << "  in Socket::recv\n";
        return 0;
    }
    else if ( status == 0 )
    {
        return 0;
    }
    else
    {
        s = buf;
        return status;
    }
}



bool Socket::connect ( const std::string host, const int port )
{
    if ( ! is_valid() ) return false;

    m_addr.sin_family = AF_INET;
    m_addr.sin_port = htons ( port );

    int status = inet_pton ( AF_INET, host.c_str(), &m_addr.sin_addr );

    if ( errno == EAFNOSUPPORT ) return false;

    status = ::connect ( m_sock, ( sockaddr * ) &m_addr, sizeof ( m_addr ) );

    if ( status == 0 )
        return true;                                                                                                
    else
        return false;
}
void Socket::set_non_blocking ( const bool b )
{

    int opts;

    opts = fcntl ( m_sock,
                   F_GETFL );

    if ( opts < 0 )
    {
        return;
    }

    if ( b )
        opts = ( opts | O_NONBLOCK );
    else
        opts = ( opts & ~O_NONBLOCK );

    fcntl ( m_sock,
            F_SETFL,opts );

} 
3.sock_exception.h文件

#ifndef SOCKET_EXCEPTION_H
#define SOCKET_EXCEPTION_H

#include <string>

class SocketException
{
 public:
  SocketException ( std::string s ) : m_s ( s ) {}; 
  ~SocketException (){};

  std::string description() { return m_s; }

 private:

  std::string m_s;

};

#endif
4.server_socket.h文件

#ifndef SERVER_SOCKET_H
#define SERVER_SOCKET_H

#include "socket.h"


class ServerSocket : private Socket
{
public:

    ServerSocket ( int port );
    ServerSocket () {}; 
    virtual ~ServerSocket();

    const ServerSocket& operator << ( const std::string& ) const;
    const ServerSocket& operator >> ( std::string& ) const;

    void accept ( ServerSocket& );

};


#endif
5.server_socket.cpp文件

#include "server_socket.h"
#include "socket_exception.h"


ServerSocket::ServerSocket ( int port )
{
    if ( ! Socket::create() )
    {   
        throw SocketException ( "Could not create server socket." );
    }   

    if ( ! Socket::bind ( port ) ) 
    {   
        throw SocketException ( "Could not bind to port." );
    }   

    if ( ! Socket::listen() )
    {   
        throw SocketException ( "Could not listen to socket." );
    }   

}

ServerSocket::~ServerSocket()
{
}


const ServerSocket& ServerSocket::operator << ( const std::string& s ) const
{
    if ( ! Socket::send ( s ) ) 
    {   
        throw SocketException ( "Could not write to socket." );
    }   

    return *this;

}
const ServerSocket& ServerSocket::operator >> ( std::string& s ) const
{
    if ( ! Socket::recv ( s ) ) 
    {   
        throw SocketException ( "Could not read from socket." );
    }

    return *this;
}

void ServerSocket::accept ( ServerSocket& sock )
{
    if ( ! Socket::accept ( sock ) )
    {
        throw SocketException ( "Could not accept socket." );
    }
} 
6.server.cpp文件

#include "server_socket.h"
#include "socket_exception.h"
#include <string>
#include <iostream>
using namespace std;

int main ( int argc, char* argv[] )
{
    std::cout << "running....\n" << std::endl;

    try 
    {   
        // Create the socket
        ServerSocket server ( 30000 );

        while ( true )
        {   

            ServerSocket new_sock;
            server.accept ( new_sock );

            try 
            {   
                while ( true )
                {   
                    std::string data;
                    new_sock >> data;
                    std::cout << "We received this response from the client:\n\"" << data << "\"\n";;               
                    new_sock << data;
                }   
            }   
            catch ( SocketException& ) {}

        }   
    }   
    catch ( SocketException& e ) 
    {   
        std::cout << "Exception was caught:" << e.description() << "\nExiting.\n";
    }   

    return 0;
}
7.client_socket.h文件

#ifndef CLIENT_SOCKET_H
#define CLIENT_SOCKET_H

#include "socket.h"                                                                                                 


class ClientSocket : private Socket
{
public:

    ClientSocket ( std::string server_addr, int port );
    virtual ~ClientSocket() {}; 

    const ClientSocket& operator << ( const std::string& ) const;
    const ClientSocket& operator >> ( std::string& ) const;

};


#endif
8.client_socket.cpp文件

#include "client_socket.h"
#include "socket_exception.h"


ClientSocket::ClientSocket ( std::string server_addr, int port )
{
    if ( ! Socket::create() )
    {   
        throw SocketException ( "Could not create client socket." );
    }   

    if ( ! Socket::connect ( server_addr, port ) ) 
    {   
        throw SocketException ( "Could not bind to port." );
    }   

}


const ClientSocket& ClientSocket::operator << ( const std::string& s ) const
{
    if ( ! Socket::send ( s ) ) 
    {   
        throw SocketException ( "Could not write to socket." );
    }   

    return *this;

}


const ClientSocket& ClientSocket::operator >> ( std::string& s ) const
{
    if ( ! Socket::recv ( s ) ) 
    {   
        throw SocketException ( "Could not read from socket." );
    }   

    return *this;
}  
9.client.cpp文件

#include "client_socket.h"
#include "socket_exception.h"
#include <iostream>
#include <string>
using namespace std;

const string kServer_Address = "192.168.0.109";

int main ( int argc, char* argv[] )
{
    try 
    {   

        ClientSocket client_socket ( kServer_Address, 30000 );

        std::string reply;

        try 
        {   
            if(argc == 2)
            {   
                client_socket << argv[1];
                client_socket >> reply;
            }                                                                                                       
        }   
        catch ( SocketException& ) {}

        std::cout << "We received this response from the server:\n\"" << reply << "\"\n";;

    }   
    catch ( SocketException& e ) 
    {   
        std::cout << "Exception was caught:" << e.description() << "\n";
    }   

    return 0;
}
10.Makefile文件

all : simple_server simple_client

simple_server:socket.o server_socket.o server.o
    g++ -o simple_server socket.o server_socket.o server.o
simple_client:socket.o client_socket.o client.o
    g++ -o simple_client socket.o client_socket.o client.o

socket.o: socket.cpp socket.h
    g++ -c socket.cpp                                                                                               
server_socket.o: server_socket.cpp server_socket.h socket_exception.h
    g++ -c server_socket.cpp
client_socket.o: client_socket.cpp client_socket.h socket_exception.h
    g++ -c client_socket.cpp
client.o:client.cpp
    g++ -c client.cpp
server.o:server.cpp
    g++ -c server.cpp

clean:
    rm -f *.o simple_server simple_client


执行make即可

[jingsia@localhost socket]$ make
g++ -c socket.cpp
g++ -c server_socket.cpp
g++ -c server.cpp
g++ -o simple_server socket.o server_socket.o server.o
g++ -c client_socket.cpp
g++ -c client.cpp
g++ -o simple_client socket.o client_socket.o client.o
生成:



运行:

1.服务端启动

[jingsia@localhost socket]$ ./simple_server 
running....
2.客户端发送消息至服务端

[jingsia@localhost socket]$ ./simple_client "simple socket test"
We received this response from the server:
"simple socket test"
3.服务器接收显示

[jingsia@localhost socket]$ ./simple_server 
running....

We received this response from the client:
"simple socket test"
注意:

1.client设置服务器IP地址和端口号



源码可下载地址:https://github.com/jingsia/simple-socket-demo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值