FDX通信——上位机服务器
#include "stdafx.h"
#include "FDXSocket.h"
#include "FDXDatagram.h"
#include <WS2tcpip.h>
//服务器
void FDXSocket::Open()
{
//---------------------------------------------
// Initialize Winsock
if (!mWSAstarted)
{
WSADATA wsaData;
int startupResult = WSAStartup(MAKEWORD(2,2), &wsaData);//初始化socket动态库
if (startupResult!=0)
{
printf("FDXSocket: WSAStartup failed \n");
return;
}
mWSAstarted = true;
}
//---------------------------------------------
/* WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);用于创建一个UDP套接字(socket)。
- 参数解析:
- AF_INET:指定地址族为IPv4。
- SOCK_DGRAM:指定套接字类型为数据报套接字,适用于UDP。
- IPPROTO_UDP:指定协议为UDP。
- NULL, 0, 0:分别表示无特定协议信息、无特定组标识、无特定窗口句柄。
- 操作说明:
调用WSASocket函数创建UDP套接字。
将返回的套接字句柄赋值给mSocket变量。
若创建成功,mSocket将用于后续UDP通信操作。*/
// Create a socket for sending data
mSocket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);//创建一个 UDP socket
if (mSocket==INVALID_SOCKET)
{
printf("FDXSocket: creation of socket failed \n");
return;
}
// set a 1000 ms timeout for receive operations
/*setsockopt函数用于设置给定套接字选项的值。针对接收超时(SO_RCVTIMEO)的设置
第一个参数mSocket是套接字文件描述符。
第二个参数SOL_SOCKET指定选项所在的协议层。
第三个参数SO_RCVTIMEO指定要操作的套接字选项,即接收超时。
第四个参数是将timeout的地址转换为const char*类型。
第五个参数是timeout结构体的大小。
处理返回值:
返回值:
成功时,setsockopt返回0。
失败时,返回-1,并设置errno以指示错误原因。*/
int timeout = 1000;
int rc = setsockopt(mSocket, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<const char*>(&timeout), sizeof(timeout));
if (rc!=0)
{
printf("FDXSocket: Failed to set receive timeout \n");
}
//-----------------------------------------------
/*- bind()
功能描述:绑定套接字与地址
-参数解析:
mSocket:套接字文件描述符。
(SOCKADDR*) &RecvAddr:指向RecvAddr的指针,RecvAddr包含地址信息,需转换为SOCKADDR*类型。
sizeof(RecvAddr):RecvAddr结构体的大小。
- 操作结果:
成功:rcBind返回0,表示套接字与地址成功绑定。
失败:rcBind返回 - 1,表示绑定失败,可通过检查errno获取错误原因*/
// Bind the socket to any address and the specified port.
int myPort = 2010;
sockaddr_in RecvAddr;
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(myPort);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
int rcBind = bind(mSocket, (SOCKADDR*) &RecvAddr, sizeof(RecvAddr));
if (rcBind!=0)
{
printf("FDXSocket: bind operation failed \n");
Close();
return;
}
//---------------------------------------------------
// reset sequence numbering// 设置下一个传输序列号的起始值。//通常发生在通信会话初始化阶段,用于标识会话的开始。
mNextTransmitSequenceNumber = CANoeFDX::kSequenceNumberSessionStart;
}