服务器处于活动状态时重新连接asio连接

时间:2015-08-27 11:43:36

标签: c++ tcp go boost-asio

我想保持asio连接响应,我的意思是每秒检查一次服务器,直到它变为活着,然后发送和接收。这是我的代码

--- --- irunnable.h

#ifndef IRUNNABLE_H
#define IRUNNABLE_H

#include <condition_variable>
#include <atomic>
#include <thread>

class IRunnable
{
public:
    IRunnable(): mThread(nullptr) {
        mRunning.store(false);
    }

    virtual ~IRunnable() {
        if (mRunning.load())
            Stop();
        delete mThread;
    }


    virtual void Start() {
        mRunning.store(true);
        mThread = new std::thread(&IRunnable::Run, this);
    }

    virtual void Stop() {
        mRunning.store(false);
        if (mThread && mThread->joinable())
            mThread->join();
    }

    virtual bool IsRunning() {return mRunning.load();}

protected:
    virtual void Run() = 0;

    std::atomic<bool> mRunning;

private:
    std::thread *mThread;
};

#endif // IRUNNABLE_H

--- --- mytcpconnection.h

#ifndef MYTCPCONNECTION_H
#define MYTCPCONNECTION_H

#include <asio/io_service.hpp>
#include <asio/ip/tcp.hpp>
#include "irunnable.h"


class MyTCPConnection : public IRunnable
{
public:
    MyTCPConnection(const std::string &ip, const std::string &port);

    ~MyTCPConnection();

    void Stop();

    void Write(const std::string &msg);

    void Connect();
protected:
    void Run();

private:
    void readHeader();

private:
    std::string mIP;
    std::string mPort;
    asio::io_service mIOService;
    asio::ip::tcp::socket mSocket;
};

#endif // MYTCPCONNECTION_H

--- mytcpconnection.cpp

#include "mytcpconnection.h"
#include <iostream>
#include <asio/connect.hpp>
#include <asio/write.hpp>
#include <asio/read.hpp>

MyTCPConnection::MyTCPConnection(const std::string &ip, const std::string &port):
    mIP(ip),
    mPort(port),
    mSocket(mIOService)
{
    Connect();
}

MyTCPConnection::~MyTCPConnection()
{
    Stop();
}

void MyTCPConnection::Stop()
{
    mIOService.stop();
    mSocket.close();
    IRunnable::Stop();
}

void MyTCPConnection::Write(const std::string &msg)
{
    asio::async_write(mSocket,
                    asio::buffer(msg.c_str(),
                                msg.length()),
                    [this, msg](std::error_code ec, std::size_t /*length*/)
    {
        if (!ec)
        {
            std::cout <<  msg << std::endl;
        }
        else
        {
            mSocket.close();
        }
    });
}



void MyTCPConnection::Run()
{

    while (mRunning.load()) {
        sleep(1);
//        Connect();
        std::cout << "before run\n";
        mIOService.run();
        std::cout << "after run\n";
    }

}

void MyTCPConnection::Connect()
{
    asio::ip::tcp::resolver resolver(mIOService);
    asio::async_connect(mSocket, resolver.resolve({mIP, mPort}),
                        [this](std::error_code ec, asio::ip::tcp::resolver::iterator)
    {
        if (!ec)
        {
            std::cout << "readHeader called\n";
            readHeader();
        }
        else {
            std::cout << "can not connect\n";
            mSocket.close();
            mIOService.reset();
            std::cout << "after stopping io_service\n";
        }
    });
}

void MyTCPConnection::readHeader()
{
    const int header_length = 16;
    std::shared_ptr<char> msg(new char[header_length]{0},
        [](char *c) {
            delete[] c;
    });
    asio::async_read(mSocket,
                    asio::buffer(msg.get(), header_length),
                    [this, msg](std::error_code ec, std::size_t s/*length*/)
    {
        if (!ec)
        {
            std::cout << "Message read " << s << std::endl;
            readHeader();
        }
        else
        {
            std::cout << "closing socket\n";
            mSocket.close();
            mIOService.stop();
        }
    });
}

--- --- main.cpp中

#include <iostream>
#include "mytcpconnection.h"

using namespace std;

int main()
{
    MyTCPConnection conn("127.0.0.1", "12345");
    conn.Start();

    while (true)
    {
        conn.Write("Hello server");

        sleep(1);
    }

    return 0;
}

--- --- server.go

package main

import (
        "time"
        "fmt"
        "net"
)

func handle_conn(conn net.Conn) {
    b := make([]byte, 1028)
    for {
        n, err:= conn.Read(b)
        if err != nil {
            fmt.Println(err.Error())
            break
        }
        fmt.Println(string(b[:n]))
        _, _ = conn.Write([]byte("hellohellohello1"))
        time.Sleep(time.Second*1)
    }
}

func main() {
        ln, err := net.Listen("tcp", ":12345")
        if err != nil {
                fmt.Println(err.Error())
        }
        fmt.Println("server started")
        for {
                conn, err := ln.Accept()
        fmt.Println("connection from", conn.RemoteAddr())
                if err != nil {
                        fmt.Println(err.Error())
                        continue
                }
                go handle_conn(conn)
        }
}

在此表单中,客户端连接到服务器(在服务器运行时)并继续读写。如果我将mytcpconnection构造函数中的Connect()方法移动到Run()函数(现在进行注释),则连接无法连接到服务器。

如何解决此问题?

0 个答案:

没有答案