一.问题:
VS实现PC软件和单片机的网络连接的时候,如果网线没有插入,检测连接失败,一般设置网络连接为非阻塞方式,但是如果单片机返回比较慢,会导致正常情况下也连不上,下面代码通过
设置等待方法解决此问题
二.代码如下:
1.连接代码
WSADATA wsaData;
g_Socket = INVALID_SOCKET;
struct addrinfo* result = NULL, * ptr = NULL, hints;
int iResult;
// 初始化 Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
return -1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// 解析服务器地址和端口
iResult = getaddrinfo(ServerIP, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return -1;
}
ptr = result;
// 创建套接字
g_Socket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (g_Socket == INVALID_SOCKET) {
printf("socket failed: %ld\n", WSAGetLastError());
WSACleanup();
return -1;
}
socket_nonblock(g_Socket);
// 连接到服务器
iResult = connect(g_Socket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) { //非阻塞模式可能太快没有连接成功,这里再进行延时检测
int error = WSAGetLastError();
if (error == WSAEWOULDBLOCK) {
// 连接操作正在进行中
fd_set writefds;
FD_ZERO(&writefds);
FD_SET(g_Socket, &writefds);
struct timeval timeout = { 1, 0 }; // 1秒超时
int result = select(0, NULL, &writefds, NULL, &timeout);
if (result > 0 && FD_ISSET(g_Socket, &writefds))
{
int err;
socklen_t errlen = sizeof(err);
getsockopt(g_Socket, SOL_SOCKET, SO_ERROR, (char*)&err, &errlen);
if (err == 0) {
// 连接成功
printf("Connected successfully.\n");
}
else {
// 连接失败,处理错误
printf("Connect failed with error: %d\n", err);
closesocket(g_Socket);
g_Socket = INVALID_SOCKET;
return -1;
}
}
else
{
// 超时或其他错误
printf("Connect timed out or error occurred.\n");
closesocket(g_Socket);
g_Socket = INVALID_SOCKET;
return -1;
}
}
else
{
// 其他连接错误
printf("Connect failed with error 2: %d\n", error);
closesocket(g_Socket);
g_Socket = INVALID_SOCKET;
return -1;
}
}
else
{
// 连接成功
printf("Connected immediately.\n");
}
freeaddrinfo(result);
2.子函数
int socket_nonblock(SOCKET sock) {
int mode;
mode = 1;
return ioctlsocket(sock, FIONBIO, &mode);
}