c++简单的udp收发类

/***************************************udpclient.h******************************/
 
#ifndef UDP_CLIENT_H
#define UDP_CLIENT_H
#include <winsock.h>
 
class Clientudp
{
public:
	Clientudp();
	bool InitializeClient(const char* ip, int local_port, int remote_port = -1);
	void SetReadTimeout(int timeout_ms);
	int PushToWriteBuffer(const char* msg, unsigned int size);
	int PullFromReadBuffer(char* msg, unsigned int size);
	bool GetClientStatus();
    bool GetRemoteAddress(sockaddr_in* addr);
	~Clientudp();
private:
	int m_fd_;
	int m_read_timeout = -1;
	bool m_socket_avaliable_ = false;
	sockaddr_in m_remote_addr_;
	int m_remote_port_ = -1;
	sockaddr_in m_bind_addr_;
};
 
#endif
 
 
 
/*************************************udpclient.cpp***************************/
 
#include <iostream>
#include "UdpClient.h"
 
Clientudp::Clientudp()
{}
 
Clientudp::~Clientudp()
{
    if(m_socket_avaliable_)
        closesocket(m_fd_);
}
 
void Clientudp::SetReadTimeout(int timeout_ms)
{
	m_read_timeout = timeout_ms;
}
 
bool Clientudp::InitializeClient(const char* ip, int local_port, int remote_port)
{
	if (m_socket_avaliable_)
	{
		closesocket(m_fd_);
		m_socket_avaliable_ = false;
	}
	if ((m_fd_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
	{
		// create socket failed.
		m_socket_avaliable_ = false;
		return m_socket_avaliable_;
	}
	if (m_read_timeout > 0)
	{
		struct timeval read_timeout = { m_read_timeout, 0 };
		setsockopt(m_fd_, SOL_SOCKET, SO_RCVTIMEO, (char *)&read_timeout, sizeof(struct timeval));
	}
	memset(&m_remote_addr_, 0, sizeof(m_remote_addr_));
	m_remote_addr_.sin_family = AF_INET;
	m_remote_addr_.sin_addr.s_addr = inet_addr(ip);
	m_remote_addr_.sin_port = htons(remote_port);
	m_remote_port_ = remote_port;
	memset(&m_bind_addr_, 0, sizeof(m_bind_addr_));
	m_bind_addr_.sin_family = AF_INET;
	m_bind_addr_.sin_addr.s_addr = htonl(INADDR_ANY);
	m_bind_addr_.sin_port = htons(local_port);
 
	if (bind(m_fd_, (SOCKADDR*)&m_bind_addr_, sizeof(m_bind_addr_)) == SOCKET_ERROR)
	{
		int error_code = WSAGetLastError();
		if (error_code == WSAEADDRINUSE)
			printf("The port %d on this machine has been Occqupied.\n", local_port);
		printf("Bind Client to Fixed address Failed, Then you should settle a correct remote port and send data to remote machine before recv.\n");
		if (m_remote_port_ <= 0)
		{
			printf("InitializeClient Failed, Remote port = %d seems not to be a valid port number.\n", m_remote_port_);
			closesocket(m_fd_);
			m_socket_avaliable_ = false;
			return false;
		}
	}
	m_socket_avaliable_ = true;
	return m_socket_avaliable_;
}
 
int Clientudp::PushToWriteBuffer(const char* msg, unsigned int size)
{
	if (!m_socket_avaliable_)
	{
		return -1;
	}
	int ret = sendto(m_fd_, msg, size, 0, (sockaddr*)&m_remote_addr_, sizeof(m_remote_addr_));
	if (ret == SOCKET_ERROR)
	{
		int error_code = WSAGetLastError();
		//printf("error_code: %d\n",error_code);
		if (m_remote_port_ < 0 && error_code == WSAEINVAL)
		{
			printf("You should recv data from peer firstly before send.\n");
			return 0;
		}
		closesocket(m_fd_);
		m_socket_avaliable_ = false;
		m_remote_port_ = -1;
		return -1;
	}
	else
	{
		return ret;
	}
}
 
int Clientudp::PullFromReadBuffer(char* msg, unsigned int size)
{
	if (!m_socket_avaliable_)
	{
		return -1;
	}
	int addr_len = sizeof(m_remote_addr_);
	int ret = recvfrom(m_fd_, msg, size, 0, (sockaddr*)&m_remote_addr_, &addr_len);
	if (ret == SOCKET_ERROR)
	{
		int error_code = WSAGetLastError();
		if (error_code == WSAEMSGSIZE || error_code == WSAEINTR || error_code == WSAETIMEDOUT || error_code == WSAEWOULDBLOCK)
		{
            if(error_code == WSAEMSGSIZE)//datagram is too large to put into msg buffer.
                memset(msg,0x00,size);
			return 0;
		}
		else
		{
			closesocket(m_fd_);
			m_socket_avaliable_ = false;
			return -1;
		}
	}
	else
	{
		return ret;
	}
}
 
bool Clientudp::GetClientStatus()
{
	return m_socket_avaliable_;
}
 
bool Clientudp::GetRemoteAddress(sockaddr_in* addr)
{
    if(!m_socket_avaliable_)
        return false;
    if (m_remote_port_ <= 0)
    {
        int asize;
        getpeername(m_fd_, (sockaddr*)&m_remote_addr_, &asize);
        m_remote_port_ = ntohs(m_remote_addr_.sin_port);
        if (m_remote_port_ <= 0)
            return false;
    }
    *addr = m_remote_addr_;
    return true;
}

#include <iostream>
#include "udpclient.h"
 
int main()
{
    WSADATA ws
    WSAStartup(MAKEWORD(2,2),&ws);
    Clientudp udp;
    udp.InitializeClient("127.0.0.1", 1234, -1);
    char RxBuffer[1024];
    char TxBuffer[1024];
    memset(RxBuffer,0x00,1024);
    memset(TxBuffer,0x00,1024);
    /*如果remote_port为-1,则目的端口号未知,只能先收再发。如果知道对方端口号,则收发顺序可随便*/
    int readLen= udp.PullFromReadBuffer(RxBuffer,1024);
    printf("Read message length: %d",readLen);
    int writeLen = sprintf_s(TxBuffer,1023,"hello world");
    udp.PushToWriteBuffer(TxBuffer,writeLen);
    getchar();
    WSACleanup();   
    return 0;
}

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值