VS2015
win32控制台应用程序
我建的类名为MyUdpSocket,
MyUdpSocket.h头文件如下:
#pragma once
#include
#include
#include
#include
using namespace std;
class MyUdpSocket
{
public:
MyUdpSocket();
~MyUdpSocket();
bool Initial(int nlocalPort, string strLocalIP, int nRemotePort, string strRemoteIP, bool bBlockMode = true);
bool RecvData(std::vector& vReplay);
bool SendData(std::vector& vSendData);
void SetSocketSize(SOCKET sock,int nsize);
public:
SOCKET m_pcSocket;
sockaddr_in m_pcAddr;
sockaddr_in m_deviceCmdAddr;
};
MyUdpSocket.cpp源文件如下:
#include "stdafx.h"
#include "MyUdpSocket.h"
MyUdpSocket::MyUdpSocket()
{
}
MyUdpSocket::~MyUdpSocket()
{
}
bool MyUdpSocket::Initial(int nlocalPort, string strLocalIP, int nRemotePort, string strRemoteIP, bool bBlockMode)
{
WSADATA wsaData0;
if (0 == WSAStartup(MAKEWORD(2, 2), &wsaData0))
{
m_pcSocket = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
unsigned long iMode = 0;
if (!bBlockMode)
{
iMode = 1;
}
int nResult = ::ioctlsocket(m_pcSocket, FIONBIO, &iMode);//FIONBIO:允许或禁止套接口s的非阻塞模式。iMode:允许非阻塞模式则非零,如禁止非阻塞模式则为零
if (m_pcSocket == INVALID_SOCKET)
{
printf("INVALID_SOCKET!");
}
m_pcAddr.sin_family = AF_INET;
m_pcAddr.sin_port = ::htons((UINT)(nlocalPort));
//m_pcAddr.sin_addr.S_un.S_addr = ::htonl(INADDR_ANY);
m_pcAddr.sin_addr.S_un.S_addr = inet_addr(strLocalIP.c_str());
int nRet = ::bind(m_pcSocket, (sockaddr*)&m_pcAddr, sizeof(sockaddr));
if (nRet != 0)
{
printf("%s Socket bind failed!", strLocalIP.c_str());
return false;
}
SetSocketSize(m_pcSocket,10);//设置SOCKET缓冲区大小,10表示10*8192字节
m_deviceCmdAddr.sin_family = AF_INET;
m_deviceCmdAddr.sin_port = ::htons(nRemotePort);
m_deviceCmdAddr.sin_addr.S_un.S_addr = inet_addr(strRemoteIP.c_str());
}
return true;
}
bool MyUdpSocket::RecvData(std::vector& vReplay)
{
sockaddr_in deviceAddr;
int nAddrLen = sizeof(deviceAddr);
int nDataLen = (int)vReplay.size();
int nRet = ::recvfrom(m_pcSocket, (char*)&vReplay[0], nDataLen, 0, (SOCKADDR*)&deviceAddr, &nAddrLen);
//int nRet = ::recvfrom(m_pcSocket, (char*)&vReplay[0], 568, 0, (SOCKADDR*)&deviceAddr, &nAddrLen);
if (nRet > 0)
{
return true;
}
else
{
return false;
}
}
bool MyUdpSocket::SendData(std::vector& vSendData)
{
char* ctemp = (char*)malloc(vSendData.size());
memcpy(ctemp,&vSendData[0],vSendData.size());
int nSendDataLen = (int)vSendData.size();
int nResult = sendto(m_pcSocket, (char*)&vSendData[0], nSendDataLen, 0, (SOCKADDR*)&m_deviceCmdAddr, sizeof(SOCKADDR));
if (nResult == nSendDataLen)
{
return true;
}
else
{
return false;
}
}
void MyUdpSocket::SetSocketSize(SOCKET sock, int nsize)//设置缓冲区大小
{
int nErrCode = 0;
unsigned int uiRcvBuf = 0;
unsigned int uiNewRecvBuf = 0;
int uiRecvBufLen = sizeof(uiRcvBuf);
nErrCode = getsockopt(sock,SOL_SOCKET,SO_SNDBUF,(char*)&uiRcvBuf,&uiRecvBufLen);
if (SOCKET_ERROR == nErrCode)
{
printf("获取服务端设置SOCKET发送缓冲区大小失败");
return;
}
uiRcvBuf = uiRcvBuf*nsize;//设置系统发送数据为默认的倍数
nErrCode = setsockopt(sock,SOL_SOCKET,SO_SNDBUF,(char*)&uiRcvBuf,uiRecvBufLen);
if (SOCKET_ERROR == nErrCode)
{
printf("设置SOCKET发送缓冲区大小失败");
return;
}
}
注意:在stdafx.h文件中需要添加如下代码:
#define _WINSOCK_DEPRECATED_NO_WARNINGS 1
// 关闭对某些常见但经常可放心忽略的警告消息的隐藏
用法如下:
首先在头文件中包含该MyUdpSocket.h
#include "MyUdpSocket.h"
然后定义类对象,并调用初始化函数,设置本地及远端的端口和IP
MyUdpSocket *m_socketRecvCommand = new MyUdpSocket;
m_socketRecvCommand->Initial(1111, "192.168.5.11", 1111, "192.168.5.10");//(本地端口,本地IP,远端设备端口,远端设备IP)
注意:该socket默认是阻塞式的,若想设置成非阻塞式则Initial时候需增加一个bool变量,如下:
m_socketRecvCommand->Initial(1111, "192.168.5.11", 1111, "192.168.5.10",false);
接数据:
std::vector vRecvCommand(512, 0);//定义一个512字节容量的vector容器vRecvCommand
m_socketRecvCommand->RecvData(vRecvCommand)//调用接收函数,若接到数据则数据存放在vRecvCommand中
发数据:
vector vSendData(nPacketLen, 0);
memcpy(&vSendData[0], &m_packetReCommand, nPacketLen);//m_packetReCommand是一个存放好需要发送数据的结构体
m_socketRecvCommand->SendData(vSendData);