使用poco库,实现tcp client例子

base_socket_connector.h文件,可以不用改动:

#ifndef _BASE_SOCKET_CONNECTOR_H_
#define _BASE_SOCKET_CONNECTOR_H_

#include <iostream>

#include "Poco/Net/Net.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Observer.h"




typedef void (*CliSendCbFunc)(void *send_args, unsigned char *send_data, int max_send_len, int &send_len);
typedef void (*CliRecvCbFunc)(void *recv_args, unsigned char *recv_data, int &recv_len);

typedef struct TcpClientCallbackData
{
    CliSendCbFunc send_loaddata; // 装载待发送数据,send_data是要发送的数据,send_len是要发送的长度
    CliRecvCbFunc recv_callback; // 收到数据后的回调函数,recv_data是接收到的数据,recv_len是接收的数据长度

    unsigned char *send_buf; // 使用者提供的发送数据缓存空间,调用send_loaddata函数后,先将待发送数据拷贝到这里
    unsigned char *recv_buf; // 使用者提供的接收数据缓存空间,当系统有可接收数据时,先接收到这里,再调用recv_callback,传递给使用者
    int send_len;            // 实际发送数据的长度
    int max_send_len;        // send_buf的最大长度
    int max_recv_len;        // recv_buf的最大长度

    void *send_args; // 存放使用者自己的私有数据
    void *recv_args; // 存放使用者自己的私有数据
} TcpClientCallbackData;

template <class TcpClientHandle>
class BaseSocketConnector
{
  public:
    explicit BaseSocketConnector(Poco::Net::SocketAddress &address) : socket_reactor_(0)
    {
        stream_socket_.connectNB(address);
    }

    BaseSocketConnector(Poco::Net::SocketAddress &address,
                        Poco::Net::SocketReactor &reactor,
                        TcpClientCallbackData &tcp_client_callback) : socket_reactor_(0)
    {
        stream_socket_.connectNB(address);
        RegisterConnector(reactor);

        tcp_client_callback_ = tcp_client_callback;
    }

    virtual ~BaseSocketConnector()
    {
        try
        {
            UnregisterConnector();
        }
        catch (...)
        {
            poco_unexpected();
        }
    }

    virtual void RegisterConnector(Poco::Net::SocketReactor &reactor)
    {
        socket_reactor_ = &reactor;
        socket_reactor_->addEventHandler(stream_socket_, Poco::Observer<BaseSocketConnector, Poco::Net::ReadableNotification>(*this, &BaseSocketConnector::OnReadable));
        socket_reactor_->addEventHandler(stream_socket_, Poco::Observer<BaseSocketConnector, Poco::Net::WritableNotification>(*this, &BaseSocketConnector::OnWritable));
        socket_reactor_->addEventHandler(stream_socket_, Poco::Observer<BaseSocketConnector, Poco::Net::TimeoutNotification>(*this, &BaseSocketConnector::OnTimeout));
        socket_reactor_->addEventHandler(stream_socket_, Poco::Observer<BaseSocketConnector, Poco::Net::ErrorNotification>(*this, &BaseSocketConnector::OnError));
    }

    virtual void UnregisterConnector()
    {
        if (socket_reactor_)
        {
            socket_reactor_->removeEventHandler(stream_socket_, Poco::Observer<BaseSocketConnector, Poco::Net::ReadableNotification>(*this, &BaseSocketConnector::OnReadable));
            socket_reactor_->removeEventHandler(stream_socket_, Poco::Observer<BaseSocketConnector, Poco::Net::WritableNotification>(*this, &BaseSocketConnector::OnWritable));
            socket_reactor_->removeEventHandler(stream_socket_, Poco::Observer<BaseSocketConnector, Poco::Net::TimeoutNotification>(*this, &BaseSocketConnector::OnTimeout));
            socket_reactor_->removeEventHandler(stream_socket_, Poco::Observer<BaseSocketConnector, Poco::Net::ErrorNotification>(*this, &BaseSocketConnector::OnError));
        }
    }

    void OnReadable(Poco::Net::ReadableNotification *readable_notification)
    {
        readable_notification->release();
        int err = stream_socket_.impl()->socketError();
        if (err)
        {
            OnError(err);
            UnregisterConnector();
        }
        else
        {
            OnConnect();
        }
    }

    void OnWritable(Poco::Net::WritableNotification *writable_notification)
    {
        writable_notification->release();
        OnConnect();
    }

    void OnConnect()
    {
        stream_socket_.setBlocking(true);
        NewTcpClientHandle();
        UnregisterConnector();
    }

    void OnError(Poco::Net::ErrorNotification *error_notification)
    {
        error_notification->release();
        OnError(stream_socket_.impl()->socketError());
    }

    void OnTimeout(Poco::Net::TimeoutNotification *timeout_notification)
    {
        timeout_notification->release();
        OnError(stream_socket_.impl()->socketError());
    }

    //
    void GetSendLen(int &send_len)
    {
        send_len = tcp_client_callback_.send_len;
    }

  protected:
    virtual TcpClientHandle *NewTcpClientHandle()
    {
        return new TcpClientHandle(stream_socket_, socket_reactor_, tcp_client_callback_);
    }

    virtual void OnError(int errorCode)
    {
        socket_reactor_->stop();
        stream_socket_.close();
    }

    Poco::Net::SocketReactor *GetReactor()
    {
        return socket_reactor_;
    }

    Poco::Net::StreamSocket &GetSocket()
    {
        return stream_socket_;
    }

  private:
    BaseSocketConnector();
    BaseSocketConnector(const BaseSocketConnector &);
    BaseSocketConnector &operator=(const BaseSocketConnector &);

    Poco::Net::StreamSocket stream_socket_;
    Poco::Net::SocketReactor *socket_reactor_;

    //
    TcpClientCallbackData tcp_client_callback_;
};



#endif // _BASE_SOCKET_CONNECTOR_H_

base_tcp_client.h,根据应用,可以进行修改:

#ifndef _BASE_TCP_CLIENT_H_
#define _BASE_TCP_CLIENT_H_

#include <iostream>

#include "base_socket_connector.h"



#include "Poco/Net/Net.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Observer.h"



class BaseTcpClient
{
  public:
    BaseTcpClient(Poco::Net::StreamSocket &socket, 
                  Poco::Net::SocketReactor *reactor,
                  TcpClientCallbackData &tcp_client_callback) : socket_(socket),
                                                                reactor_(reactor),
                                                                on_readable_(*this, &BaseTcpClient::OnReadable),
                                                                on_writable_(*this, &BaseTcpClient::OnWritable),
                                                                on_timeout_(*this, &BaseTcpClient::OnTimeout),
                                                                timeout_(false),
                                                                close_on_timeout_(false),
                                                                tcp_client_callback_(0)
    {
        tcp_client_callback_ = &tcp_client_callback;

        reactor_->addEventHandler(socket_, on_readable_);
        reactor_->addEventHandler(socket_, on_writable_);
        reactor_->addEventHandler(socket_, on_timeout_);
    }

    ~BaseTcpClient()
    {
        reactor_->removeEventHandler(socket_, Poco::Observer<BaseTcpClient, Poco::Net::ReadableNotification>(*this, &BaseTcpClient::OnReadable));
        reactor_->removeEventHandler(socket_, Poco::Observer<BaseTcpClient, Poco::Net::WritableNotification>(*this, &BaseTcpClient::OnWritable));
        reactor_->removeEventHandler(socket_, Poco::Observer<BaseTcpClient, Poco::Net::TimeoutNotification>(*this, &BaseTcpClient::OnTimeout));
    }

    void OnReadable(Poco::Net::ReadableNotification *readable_notification)
    {
        int recv_len = 0;
        readable_notification->release();

        if (NULL == tcp_client_callback_)
        {
            return;
        }

        recv_len = socket_.receiveBytes(tcp_client_callback_->recv_buf, tcp_client_callback_->max_recv_len);
        if (recv_len > 0)
        {
            // 使用者的回调函数,由使用者处理接收到的数据
            tcp_client_callback_->recv_callback(tcp_client_callback_->recv_args, tcp_client_callback_->recv_buf, recv_len);
        }
        else
        {
            std::cout << "BaseTcpClient - Read Error." << std::endl;

            reactor_->stop();
            socket_.close();
            delete this;
        }
    }

    void OnWritable(Poco::Net::WritableNotification *writable_notification)
    {
        writable_notification->release();

        if (NULL == tcp_client_callback_)
        {
            return;
        }

        
        // 回调获取使用者发送的数据
        tcp_client_callback_->send_len = -1;
        tcp_client_callback_->send_loaddata(tcp_client_callback_->send_args,
                                            tcp_client_callback_->send_buf,
                                            tcp_client_callback_->max_send_len,
                                            tcp_client_callback_->send_len);
        // 待发送数据长度大于0
        if (tcp_client_callback_->send_len >= 0)
        {
            // 调用实际发送函数
            tcp_client_callback_->send_len = socket_.sendBytes(tcp_client_callback_->send_buf, tcp_client_callback_->send_len);
        }

        if (tcp_client_callback_->send_len < 0)
        {
            std::cout << "BaseTcpClient - Wirte Error." << std::endl;
        }
    }

    void OnTimeout(Poco::Net::TimeoutNotification *timeout_notification)
    {
        timeout_notification->release();

        timeout_ = true;
        if (close_on_timeout_)
        {
            reactor_->stop();
            socket_.close();
            delete this;
        }
    }

  private:
    Poco::Net::StreamSocket socket_;
    Poco::Net::SocketReactor *reactor_;

    Poco::Observer<BaseTcpClient, Poco::Net::ReadableNotification> on_readable_;
    Poco::Observer<BaseTcpClient, Poco::Net::WritableNotification> on_writable_;
    Poco::Observer<BaseTcpClient, Poco::Net::TimeoutNotification> on_timeout_;

    bool timeout_;
    bool close_on_timeout_;

  private:
    //
    TcpClientCallbackData *tcp_client_callback_;
};


#endif // _BASE_TCP_CLIENT_H_

main.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stddef.h>
#include <unistd.h>
#include <sys/time.h>

#include <fcntl.h>
#include <termios.h>
#include <pthread.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <uv.h>

#include <iostream>
#include <sstream>

#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/Net/SocketAcceptor.h"
#include "Poco/Net/ParallelSocketAcceptor.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Observer.h"
#include "Poco/Exception.h"

#include "Poco/LocalDateTime.h"
#include "Poco/DateTime.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeParser.h"

#include "Poco/Mutex.h"
#include "Poco/Thread.h"
#include "Poco/ThreadTarget.h"

#include "base_tcp_client.h"


/*****************************************************************************
 *
 * Macro definition
 *
 *****************************************************************************/
//
#define CCT_CAMERA_SERVER_IP                        ("127.0.0.1")
#define CCT_CAMERA_SERVER_PORT                      (8080)


/*****************************************************************************
 *
 * Structure/Class definition
 *
 *****************************************************************************/

#define MAX_BUF_SIZE                2048
#define MAX_ONSEND_INTERVAL         10 /// ms


/*****************************************************************************
 *
 * Data definition
 *
 *****************************************************************************/
//
static pthread_cond_t   send_ready = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t  send_lock = PTHREAD_MUTEX_INITIALIZER;

static uint8_t  user_send_buf[2048];
static int      user_send_len;


/*****************************************************************************
 *
 * Function prototype
 *
 *****************************************************************************/
//


/*****************************************************************************
 *
 * Function entity
 *
 *****************************************************************************/
//

void PrintTimeStamp(char *str) {
    struct  timeval     tv;

    gettimeofday(&tv, NULL);
    printf("Time Stamp - %s, %ld:%ld\n\r", str, tv.tv_sec, tv.tv_usec);
}


static int StartThread(void *(*thread_entry)(void *), void *thread_para) {
    int                 rtn;
    pthread_attr_t      thread_attr;
    pthread_t           thread_ID;

    pthread_attr_init(&thread_attr);
    pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
    rtn = pthread_create(&thread_ID, &thread_attr, thread_entry, thread_para);

    return rtn;
}


void UserSendFuncLoadData_(void)
{

    pthread_mutex_lock(&send_lock);

    Poco::LocalDateTime now;
    std::string time_str = Poco::DateTimeFormatter::format(now, Poco::DateTimeFormat::ISO8601_FRAC_FORMAT);

    user_send_len = sprintf((char *)user_send_buf, "Hello, %s", time_str.c_str());

    user_send_buf[user_send_len] = 0;
    user_send_len ++;


    pthread_cond_signal(&send_ready);

    pthread_mutex_unlock(&send_lock);

}

void UserSendFuncLoadData(void *send_args, unsigned char *send_data, int max_send_len, int &send_len)
{

    pthread_mutex_lock(&send_lock);
    pthread_cond_wait(&send_ready, &send_lock);


    strcpy((char *)send_data, (char *)user_send_buf);
    send_len = sprintf((char *)send_data, "%s, %s\n\r", (char *)user_send_buf, (char *)send_args);
    send_data[send_len ++] = 0;
    //printf("%s - %s\n\r", __func__, send_data);

    pthread_mutex_unlock(&send_lock);
}

void UserRecvFuncCallback(void *recv_args, unsigned char *recv_data, int &recv_len)
{
    recv_data[recv_len] = '\0';
    std::cout << "UserRecvFuncCallback - " << recv_data << "\n\r";
}

static void *SendDataThrd(void *para) {

    while (1) {
        UserSendFuncLoadData_();

        sleep(1);
    }
}

static void TcpClientTestThrd(char *str)
{
    unsigned char recv_buf[MAX_BUF_SIZE];
    unsigned char send_buf[MAX_BUF_SIZE];

    TcpClientCallbackData tcp_client_callback_data;

    tcp_client_callback_data.recv_args = NULL;
    tcp_client_callback_data.send_args = (void *)str;

    tcp_client_callback_data.recv_callback = UserRecvFuncCallback;
    tcp_client_callback_data.send_loaddata = UserSendFuncLoadData;

    tcp_client_callback_data.send_buf = send_buf;
    tcp_client_callback_data.recv_buf = recv_buf;

    tcp_client_callback_data.max_recv_len = MAX_BUF_SIZE;
    tcp_client_callback_data.max_send_len = MAX_BUF_SIZE;


    int server_port = CCT_CAMERA_SERVER_PORT;
    std::string server_ip(CCT_CAMERA_SERVER_IP);
    Poco::Net::SocketAddress socket_addr(server_ip.c_str(), server_port);

    StartThread(SendDataThrd, NULL);

    do
    {
        SocketReactor reactor;
        BaseSocketConnector<BaseTcpClient> connector(socket_addr, reactor, tcp_client_callback_data);

        //std::cout << "before run\n\r";
        reactor.run();
        //std::cout << "after run\n\r";

        Poco::Thread::sleep(MAX_ONSEND_INTERVAL);
    } while (1);

}

int main(int argc, char ** argv)
{
    if (argc < 2) {
        printf("%s some_info\n\r", argv[0]);
        return 0;
    }
    TcpClientTestThrd(argv[1]);

    return 0;
}

makefile:

export TOP_DIR = $(PWD)

# 包含参数配置文件
#include ./Makefile.param

# 目标文件名称、编译后文件位置
PWD := $(shell pwd)
INSTALLDIR = .

TARGET = tcp_client_test
DBGTARGET = $(INSTALLDIR)/$(TARGET)d
RLSTARGET = $(INSTALLDIR)/$(TARGET)

# 配置编译器
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++
LD_CXX = $(CROSS_COMPILE)g++
STRIP = $(CROSS_COMPILE)strip
RM = rm



# 配置依赖头文件、库文件路径
INCPATH += -I. -I$(REL_INC) -I/usr/local/include 
LIBPATH += -L. -L$(REL_LIB) -L/usr/local/lib 

# 配置编译参数
FLAGS_C += $(MACRO_DEFINE) $(INCPATH) $(CFLAGS) -Wall 
FLAGS_CXX += $(MACRO_DEFINE) $(INCPATH) $(CFLAGS) -Wall 
LDFLAGS += $(CFLAGS) $(LIBPATH) $(LIBS_CFLAGS) -pie -fPIE 
LIBS += -lPocoFoundation -lPocoNet -lpthread -lm -lc -lgcc -lgcc_s -ldl 

DBG_FLAGS = -g -D__DEBUG
RLS_FLAGS = -O2 -fno-strict-aliasing


# 源文件包含
SRCS_C  = $(wildcard *.c)
SRCS_CXX  = $(wildcard *.cpp)
SRCS_H  = $(wildcard *.h*)


# obj文件包含
OBJ_DBG_DIR = 0-obj/$(CROSS_COMPILE)dbg
OBJ_RLS_DIR = 0-obj/$(CROSS_COMPILE)rls

OBJS_C_DBG = $(addprefix $(OBJ_DBG_DIR)/,$(SRCS_C:%.c=%.o))
OBJS_CXX_DBG = $(addprefix $(OBJ_DBG_DIR)/,$(SRCS_CXX:%.cpp=%.o))
OBJS_C_RLS = $(addprefix $(OBJ_RLS_DIR)/,$(SRCS_C:%.c=%.o))
OBJS_CXX_RLS = $(addprefix $(OBJ_RLS_DIR)/,$(SRCS_CXX:%.cpp=%.o))

# 编译动作
COMPILE_C = $(CC) $(FLAGS_C) -c
COMPILE_CXX = $(CXX) $(FLAGS_CXX) -c
LINK_CXX = $(LD_CXX) $(LDFLAGS) 



.PHONY: clean debug release install

all:	release

install:
	install -d $(EXEC_DIR)
	install $(RLSTARGET) $(EXEC_DIR)
	install -m 444 $(TARGET).txt $(EXEC_DIR)

release: $(RLSTARGET)
	$(STRIP) $(RLSTARGET)

debug: $(DBGTARGET)
	@echo $(TARGET)_debug_done

$(RLSTARGET):	$(OBJS_C_RLS) $(OBJS_CXX_RLS)
	@mkdir -p $(INSTALLDIR)
	$(LINK_CXX) -o $@ $^ $(LIBS) 

$(DBGTARGET):	$(OBJS_C_DBG) $(OBJS_CXX_DBG)
	@mkdir -p $(INSTALLDIR)
	$(LINK_CXX) -o $@ $^ $(LIBS) 


$(OBJS_CXX_RLS):	$(OBJ_RLS_DIR)/%.o: %.cpp $(SRCS_H)
	@mkdir -p $(OBJ_RLS_DIR)
	$(COMPILE_CXX) $(RLS_FLAGS) -o $@ $<
	
$(OBJS_C_RLS):		$(OBJ_RLS_DIR)/%.o: %.c $(SRCS_H)
	@mkdir -p $(OBJ_RLS_DIR)
	$(COMPILE_C) $(RLS_FLAGS) -o $@ $<	

$(OBJS_CXX_DBG):	$(OBJ_DBG_DIR)/%.o: %.cpp $(SRCS_H)
	@mkdir -p $(OBJ_DBG_DIR)
	$(COMPILE_CXX) $(DBG_FLAGS) -o $@ $<

$(OBJS_C_DBG):		$(OBJ_DBG_DIR)/%.o: %.c $(SRCS_H)
	@mkdir -p $(OBJ_DBG_DIR)
	$(COMPILE_C) $(DBG_FLAGS) -o $@ $<

clean:
	-$(RM) -rf  *~ *.d .dep 0-obj
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个Poco TCP客户端的完整示例代码。它连接到指定的IP地址和端口,并向服务器发送一条消息,然后等待并接收回复消息。需要注意的是,该示例使用Poco的AutoPtr来管理对象的内存,确保资源在不再需要时被正确释放。 ```c++ #include "Poco/Net/StreamSocket.h" #include "Poco/Net/SocketAddress.h" #include "Poco/AutoPtr.h" #include <iostream> using Poco::Net::StreamSocket; using Poco::Net::SocketAddress; using Poco::AutoPtr; int main(int argc, char** argv) { std::string serverAddress = "127.0.0.1"; // 服务器地址 unsigned int serverPort = 12345; // 服务器端口 // 创建客户端套接字并连接到服务器 AutoPtr<StreamSocket> socket(new StreamSocket); SocketAddress address(serverAddress, serverPort); socket->connect(address); // 发送消息 std::string message = "Hello, server!"; socket->sendBytes(message.c_str(), message.length()); // 接收回复消息 char buffer[1024]; int n = socket->receiveBytes(buffer, sizeof(buffer)); std::string reply(buffer, n); std::cout << "Received reply: " << reply << std::endl; return 0; } ``` 在上述代码中,我们首先创建了一个Poco的AutoPtr来管理StreamSocket对象的内存,确保在不再需要时正确释放资源。然后使用SocketAddress指定服务器地址和端口,并通过connect函数连接到服务器。接下来,我们发送一条消息,并使用receiveBytes函数接收服务器的回复消息,并将其打印到控制台上。 需要注意的是,该示例中的所有网络操作都是同步的,即程序会在发送和接收数据时阻塞直到操作完成。如果需要异步操作,需要使用Poco提供的异步网络编程接口。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值