Notice
Link
- Today
- Total
Recent Posts
Recent Comments
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 가변영역 스크롤
- MariaDB
- c언어
- 피쉬랜드
- 파티션 빠른 삭제
- 코드로 서버 재실행
- MySQL
- DB 계정생성
- CSS
- view 획득
- MFC
- SQL 첫날
- pid 찾아 kill
- springboot
- ffmpeg
- CentOS
- mybatis exception
- 터치좌표 view
- springboot 재가동
- vc++
- 스크롤적용
- 말줌임 CSS
- 텍스트컬러
- rn
- sql exception
- kill -9
- Activity 전체화면
- SQL 마지막날
- reactnative
- Back 키 클릭 감지
Archives
개발은 하는건가..
MFC UDP Socket Base class 본문
반응형
# Header
#pragma once
#include <afxsock.h>
#define MAX_DATA_LENGTH 1500
class CUdpSocket
{
public:
CUdpSocket();
~CUdpSocket();
friend class CUdpServer;
enum EResultCode {
EUDP_NO_OPERATION = -2,
EUDP_GENERAL_FAIL = -1,
EUDP_SUCCESS = 0,
EUDP_INVALID_DATA,
EUDP_MAX_DATA_LENGTH_OVER,
EUDP_CANCELED = WSAEINTR, // blocking operation canceled by WSACancelBlockingCall()
EUDP_BAD_SOCKET = WSAEBADF, // bad socket descriptor
EUDP_PERMISSON_DENIED = WSAEACCES, // Permission denied
EUDP_BAD_ADDRESS = WSAEFAULT, // Bad Address
EUDP_ADDR_IN_USE = WSAEADDRINUSE, // addr in used
EUDP_NET_DOWN = WSAENETDOWN, // network system fail
EUDP_NET_RESET = WSAENETRESET, // ttl expires
EUDP_CONN_RESET = WSAECONNRESET, // remote disconn or connect not avail.
EUDP_TIMEOUT = WSAETIMEDOUT, // send/recv timeout
};
virtual void AssignSocket(SOCKET sock, BOOL bCloseCurrentSocket = TRUE);
virtual SOCKET OpenSocket();
virtual void CloseSocket();
void SetSockAddr(SOCKADDR_IN* pAddr);
EResultCode SendData(__in BYTE* pData, int nDataLen);
EResultCode RecvData(__out BYTE* pRecvBuffer, __inout int& nRecvBuffLen, UINT nTimeoutMs = 0);
char* GetLastErrorMsg();
CStringW GetLastErrorMsgW(BOOL bRemoveCrLf = FALSE);
EResultCode ConvertToResultCode(int wsaErrCode);
inline SOCKADDR_IN* GetSockAddr() { return &m_SocketAddr; };
inline int GetSockAddrSize() { return sizeof(m_SocketAddr); };
inline SOCKET GetSocket() { return m_Socket; };
static inline BOOL IsHexChar(WCHAR c) { return (c >= L'0' && c <= L'9') || (c >= L'a' && c <= L'f') || (c >= L'A' && c <= L'F'); };
static inline BOOL IsSkipChar(WCHAR c) { return (c == L'\n' || c == L'\r' || c == L' ' || c == L'\t' || c == NULL); };
static BOOL ConvertHexStrToBinary(char *pszHex, BYTE *pOutBuffer, __inout int &nOutBufferLen);
static BOOL ConvertHexStrToBinary(WCHAR *pwszHex, BYTE *pOutBuffer, __inout int &nOutBufferLen);
static void ConvertBinaryToHexStr(BYTE *pData, int nDataLen, __out WCHAR *pwszOutBuff, int nOutBuffSize, int lineSplit = -1);
static void ConvertBinaryToDisplayHexStr(BYTE *pData, int nDataLen, __out WCHAR *pwszOutBuff, int nOutBuffSize, BOOL bTabIndent = TRUE);
static CString GetIpString(SOCKADDR_IN *pAddr);
private:
SOCKET m_Socket = NULL;
WSADATA m_WsaData;
SOCKADDR_IN m_SocketAddr;
char m_szLastErrMsg[MAX_PATH] = { NULL, };
};
# Cpp
#include "pch.h"
#include "UdpSocket.h"
CUdpSocket::CUdpSocket()
{
int nRes = WSAStartup(MAKEWORD(2, 2), &m_WsaData);
if (nRes != 0) {
ASSERT(0);
TRACE("CUdpSocket::CUdpSocket() - WSAStartup (Err:%d)\n", nRes);
return;
}
ZeroMemory(&m_SocketAddr, sizeof(SOCKADDR_IN));
}
CUdpSocket::~CUdpSocket()
{
CloseSocket();
if (m_WsaData.wVersion != 0) {
WSACleanup();
}
}
SOCKET CUdpSocket::OpenSocket()
{
if (m_Socket == NULL) {
m_Socket = socket(AF_INET, SOCK_DGRAM, 0); // IPPROTO_UDP
}
if (m_Socket == NULL) {
TRACE("CUdpSocket::OpenSocket() - Socket (Err:%d)\n", GetLastErrorMsg());
ASSERT(0);
}
return m_Socket;
}
void CUdpSocket::SetSockAddr(SOCKADDR_IN* pAddr)
{
if (pAddr != NULL) {
m_SocketAddr = *pAddr;
}
}
void CUdpSocket::AssignSocket(SOCKET sock, BOOL bCloseCurrentSocket) {
if (m_Socket != NULL && bCloseCurrentSocket == TRUE) {
closesocket(m_Socket);
}
m_Socket = sock;
}
CUdpSocket::EResultCode CUdpSocket::SendData(BYTE* pData, int nDataLen)
{
if (pData == NULL) {
ASSERT(0);
return EUDP_INVALID_DATA;
}
int nRes = 0;
EResultCode eResult = EUDP_SUCCESS;
SOCKET sock = OpenSocket();
if (sock == SOCKET_ERROR) {
return EUDP_GENERAL_FAIL;
}
nRes = sendto(sock, (char*)pData, nDataLen, 0, (SOCKADDR*)&m_SocketAddr, sizeof(m_SocketAddr));
if (nRes < nDataLen) {
eResult = ConvertToResultCode(WSAGetLastError());
}
return eResult;
}
CUdpSocket::EResultCode CUdpSocket::RecvData(__out BYTE* pRecvBuffer, __inout int& nRecvBuffLen, UINT nTimeoutMs)
{
EResultCode eRes = EUDP_SUCCESS;
SOCKET sock = OpenSocket();
int nRecvSize = 0;
int nSockAddrSize = sizeof(m_SocketAddr);
if (sock == -1) {
return EUDP_GENERAL_FAIL;
}
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&nTimeoutMs, sizeof(nTimeoutMs));
nRecvSize = recvfrom(sock, (char*)pRecvBuffer, nRecvBuffLen, 0, (SOCKADDR*)&m_SocketAddr, &nSockAddrSize);
if (nRecvSize == SOCKET_ERROR) {
TRACE("CUdpSocket::RecvData() - recvfrom (Err:%s)\n", GetLastErrorMsg());
eRes = ConvertToResultCode(WSAGetLastError());
}
else {
nRecvBuffLen = nRecvSize;
}
return eRes;
}
void CUdpSocket::CloseSocket()
{
if (m_Socket != NULL) {
// child 클래스에서 m_Socket 체크 루틴에서 우선 걸러지도록 m_Socket = NULL 후 closesocket() 하도록 함.
SOCKET tmpSock = m_Socket;
m_Socket = NULL;
closesocket(tmpSock);
}
}
char* CUdpSocket::GetLastErrorMsg()
{
m_szLastErrMsg[0] = NULL;
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
m_szLastErrMsg,
MAX_PATH,
NULL);
return m_szLastErrMsg;
}
CStringW CUdpSocket::GetLastErrorMsgW(BOOL bRemoveCrLf)
{
CStringW strW;
strW = GetLastErrorMsg();
if (bRemoveCrLf == TRUE) {
strW.Replace(L"\r\n", L"");
}
return strW;
}
CUdpSocket::EResultCode CUdpSocket::ConvertToResultCode(int wsaErrCode)
{
if (wsaErrCode == 0) {
return EUDP_SUCCESS;
}
else if (wsaErrCode > WSABASEERR) {
return (EResultCode)wsaErrCode;
}
return EUDP_GENERAL_FAIL;
}
// Hexstring 형식은 반드시 2자리로 구성되어야 하며 공백,\r,\n 은 자동 skip 처리 됨.
BOOL CUdpSocket::ConvertHexStrToBinary(char *pszHex, BYTE *pOutBuffer, __inout int &nOutBufferLen)
{
WCHAR wString[4096] = { NULL, };
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, wString, 4096, pszHex, _TRUNCATE);
return ConvertHexStrToBinary(wString, pOutBuffer, nOutBufferLen);
}
BOOL CUdpSocket::ConvertHexStrToBinary(WCHAR *pwszHex, BYTE *pOutBuffer, __inout int &nOutBufferLen)
{
WCHAR szHex[4] = { NULL, };
WCHAR *pPos = pwszHex;
int nSrcLen = (int)wcslen(pwszHex);
WCHAR *pEndPos = pPos + nSrcLen;
int nIncLen = 0;
if (nSrcLen < 2 || nSrcLen >(MAX_DATA_LENGTH * 4)) {
ASSERT(0);
TRACE("CUdpSocket::ConvertHexStrToBinary() - Max data length over.\n");
return FALSE;
}
while (pEndPos > pPos) {
if (IsSkipChar(*pPos) == TRUE) {
pPos++;
continue;
}
szHex[0] = *pPos++;
szHex[1] = *pPos++;
if (IsHexChar(szHex[0]) == FALSE || IsHexChar(szHex[1]) == FALSE) {
return FALSE;
}
pOutBuffer[nIncLen] = (BYTE)wcstoul(szHex, NULL, 16);
nIncLen++;
if (nIncLen >= nOutBufferLen) {
break;
}
}
nOutBufferLen = nIncLen;
return TRUE;
}
void CUdpSocket::ConvertBinaryToHexStr(BYTE *pData, int nDataLen, __out WCHAR *pOut, int nOutBuffSize, int lineSplit)
{
CStringW strHex;
pOut[0] = NULL;
for (int i = 0; i < nDataLen; i++) {
if (lineSplit > 4) {
if (i > 0 && (i % lineSplit) == 0) {
wcscat_s(pOut, nOutBuffSize, L"\r\n");
}
}
strHex.Format(L"%02X ", pData[i]);
if ((i + 1) * 3 < nOutBuffSize) {
wcscat_s(pOut, nOutBuffSize, strHex.GetBuffer(0));
}
else {
break;
}
}
}
void CUdpSocket::ConvertBinaryToDisplayHexStr(BYTE *pData, int nDataLen, __out WCHAR *pOut, int nOutBuffSize, BOOL bTabIndent)
{
CStringW strHex;
CStringW strTmp;
CStringW strTab = (bTabIndent) ? L"\t" : L"";
strHex = strTab + L"offset | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\r\n" +
strTab + L"========================================================\r\n";
for (int i = 0; i < nDataLen; i++) {
if ((i % 16) == 0) {
strTmp.Format(strTab + L"0x%04X | ", i);
if (i == 0) {
strHex.Append(strTmp);
}
else {
strHex.Append(L"\r\n");
strHex.Append(strTmp);
}
}
strTmp.Format(L"%02X ", pData[i]);
strHex.Append(strTmp);
}
strHex.Append(L"\r\n" + strTab + L"========================================================");
wcsncpy_s(pOut, nOutBuffSize, strHex.GetBuffer(0), nOutBuffSize - 1);
strHex.ReleaseBuffer();
}
CString CUdpSocket::GetIpString(SOCKADDR_IN *pAddr)
{
CString strIp;
char szIP[INET_ADDRSTRLEN];
strIp = inet_ntop(AF_INET, &(pAddr->sin_addr), szIP, INET_ADDRSTRLEN);
return strIp;
}
'C, C++, MFC' 카테고리의 다른 글
[MFC] 오른쪽 버튼 메뉴 띄우기 (custom contextmenu) (1) | 2022.09.14 |
---|---|
[VC++] 화면을 동영상으로 저장하기 (0) | 2022.09.08 |
CListCtrl 선택된 Item 인덱스 (0) | 2022.07.19 |
[MFC] DC 에 동영상 출력 시 가장 빠르게 출력 하기 위한 방법 (0) | 2022.04.08 |
[FFMPEG] H264 AvPacket 데이터를 mp4 파일로 만들기 (0) | 2022.03.14 |
Comments