多进程间的网络编程
客户端前端操作
scecreator.cpp
//发送命令
m_recvThread.sendNet(szBuf, header.usPackLen);
数据子线程
CRecvThread.cpp
void CRecvThread::sendNet(void* ptr, int len)
{
m_intfIO->sendNetData(ptr, len);
}
创建网络收发对象/创建反射内存读取对象
IntfIO.cpp
//IO操作,网络收发(NetParser* netIO;),也可反射内存(RfmParser* rfmIO; //反射内存读写)
int IntfIO::sendNetData( void* ptr, int size )
{
assert(netIO);
assert(ptr);
return netIO->sendNetData(ptr, size);
}
创建网络套接字并配置收发地址
创建套接字
必须使用socket.socket()函数
语法:
socket(socket_family, socket_type, protocol= 0)
|==||====~~~===> sock = socket(AF_INET, SOCK_DGRAM, 0);
三个参数含义:
- socket_family是AF_UNIX或AF_INET,代表套接字类型:基于文件(同一台计算机)、面向网络
- socket_type是SOCK_STREAM或SOCK_DGRAM,代表TCP(数据流)、UDP(数据报)
- protocol是默认为0
代码实现
netParaser.cpp
#include <winsoct.h>
NetParser::NetParser()
{
QString path = LSTR(".\\SceNetCfg.ini");
QSettings settings(path, QSettings::IniFormat);
localPort = settings.value("LocalPort","9130").toUInt();
SimEngineIP = settings.value("SimEngineIP","10.10.46.55").toByteArray().data();
SimEnginePort = settings.value("SimEnginePort","9131").toUInt();
sock = INVALID_SOCKET;
sendTick = 0;
}
NetParser::~NetParser()
{
// 等待仿真客户端完全退出
Sleep(1000);
if (INVALID_SOCKET != sock)
{
closesocket(sock);
sock = NULL;
}
WSACleanup();
}
void NetParser::init()
{
WSADATA wsd;
//初始化网络,配置网络参数
if (WSAStartup(MAKEWORD(2, 2), &wsd))
{
MessageBox(NULL, TEXT("网络初始化失败!"), TEXT("Error"), 0);
}
//创建套接字,绑定套接字到本地(仿真端)
sock = socket(AF_INET, SOCK_DGRAM, 0); //socket创建,三个参数:1.网络协议族(通过网络而非基于文件的本机AF_UNIX) 2.socket类型UDP(数据报datagram) 3.默认参数0
if (sock == INVALID_SOCKET)
{
MessageBox(NULL, TEXT("创建套接字失败!"), TEXT("Error"), 0);
closesocket(sock);
}
sockaddr_in _server;
memset((char*)&_server, 0, sizeof(_server));
_server.sin_family = AF_INET;
_server.sin_addr.s_addr = htonl(INADDR_ANY);
_server.sin_port = htons(localPort); //9130
//绑定socket对象到客户地址
if (bind(sock, (sockaddr *)&_server, sizeof(_server)) == SOCKET_ERROR)
{
closesocket(sock);
sock = NULL;
}
int i = 0;
ioctlsocket(sock, FIONBIO, (FAR u_long*)&i);
//设置网络通信数据:模式、IP、端口
m_addrto.sin_family = AF_INET;
m_addrto.sin_addr.s_addr = inet_addr((char*)SimEngineIP.c_str()); //"127.0.0.1"
m_addrto.sin_port = htons(SimEnginePort); //9131
}
注1:创建socket,int socket(int domain, int type, int protocol);
三个参数:domain指明所使用的协议族,通常为PF_INET/AF_INET,表示互联网协议族(TCP/IP协议族);type参数指 定socket的类型:SOCK_STREAM (TCP)或SOCK_DGRAM(UDP),Socket接口还定义了原始Socket(SOCK_RAW),允许程序使用低层协议;protocol通常赋值"0"
发送数据(续上):
netParaser.cpp
#include <winsoct.h>
int NetParser::sendNetData(void* ptr, int size)
{
assert(ptr);
int send = sendto(sock, (char*)ptr, size, 0, (struct sockaddr*)&m_addrto, sizeof(m_addrto));
int err = WSAGetLastError();
//printf("\nSend Package counter : %d, len : %d", sendTick, send);
sendTick++;
sendTick %= 0xff;
return send;
}