#include #include #include #include #pragma comment(lib, "ws2_32") bool getServerIp(uint32_t* ipv4, uint16_t* port) { // 获取物链域名服务器IP char svrName[256] = "i.ip71.cn"; HOSTENT* svrHost = gethostbyname(svrName); if (svrHost != NULL) { memcpy(ipv4, svrHost->h_addr_list[0], sizeof(uint32_t)); memcpy(port, svrHost->h_addr_list[1], sizeof(uint16_t)); return true; } return false; } int textArray(size_t* array, char* text, int length, char key) { // 从字符串转换到阵列 int index = 1; int offset = 1; array[0] = (size_t)text; for (; index < length; index++) { if (text[index] == key) { // 如果text是const空间 text[index] = 0; 会死掉! text[index] = 0; // 找到key 变为字符串结尾 array[offset] = (size_t)text + index + 1; offset += 1; } } return offset / 1; } void printfError(char* text) { // 出错显示的字眼 switch (text[1]){ case '1': printf("一般出错\r\n"); return; case '2': printf("指令格式不对\r\n"); return; case '3': printf("参数出错\r\n"); return; case '4': printf("账号名出错\r\n"); return; case '5': printf("账号密码出错\r\n"); return; case '6': printf("电器设备账号名出错\r\n"); return; case '7': printf("账号访问码出错\r\n"); return; case '9': printf("登录令牌或访问令牌出错\r\n"); return; } } bool LoginToServer(SOCKET udp, SOCKADDR_IN* addr, char* an, char* pw, char* outToken, uint32_t* outTime) { char bytes[128]; struct sockaddr_in dest_addr = { 0 }; int struct_len = sizeof(dest_addr); int length = snprintf(bytes, sizeof(bytes), "ct:ls&an:%s&pw:%s", an, pw); sendto(udp, bytes, length, 0, (struct sockaddr*)addr, sizeof(SOCKADDR_IN)); bytes[length] = 0; printf("发送%s到服务器\r\n", bytes); length = recvfrom(udp, bytes, sizeof(bytes), 0, (struct sockaddr*)&dest_addr, &struct_len); if (length > 0) { char* array[8]; bytes[length] = 0; printf("从服务器接收到%s\r\n", bytes); int lineQty = textArray((size_t*)array, bytes, length, '&'); // 从字符串转换到阵列 if (!memcmp(array[0], "ls", 2)) { // 判断array[0]是否是ls字眼 if (!memcmp(array[1], "ok", 2)) { // 判断array[1]是否是ok字眼 if (lineQty >= 4) { int tLen = (int)strlen(array[3]); memcpy(outToken, array[3], tLen+1); *outTime = atoi(array[2]); return true; } printf("出错。没有从服务器接收到数据\r\n"); return false; } printfError(array[1]); // 出错显示的字眼 return false; } printf("出错。服务器接收到数据%d\r\n", array[0]); return false; } printf("出错。没有从服务器接收到数据\r\n"); return false; } bool SyncHeartbeat(SOCKET udp, SOCKADDR_IN* addr, char* token, char* outIp) { char bytes[128]; int retry = 3; struct sockaddr_in dest_addr = { 0 }; int struct_len = sizeof(dest_addr); int length = snprintf(bytes, sizeof(bytes), "ct:sh<:%s", token); sendto(udp, bytes, length, 0, (struct sockaddr*)addr, sizeof(SOCKADDR_IN)); bytes[length] = 0; printf("发送心跳包(%s)到服务器\r\n", bytes); length = recvfrom(udp, bytes, sizeof(bytes), 0, (struct sockaddr*)&dest_addr, &struct_len); if (length > 0) { char* array[8]; bytes[length] = 0; printf("从服务器接收到%s\r\n", bytes); int lineQty = textArray((size_t*)array, bytes, length, '&'); // 从字符串转换到阵列 if (lineQty >= 3) { if (!memcmp(array[0], "sh", 2)) { if (!memcmp(array[1], "ok", 2)) { int tLen = (int)strlen(array[2]); memcpy(outIp, array[2], tLen + 1); return true; } printf("出错。没有从服务器接收到数据\r\n"); return false; } } } return true; } int main(int argc, char* argv[]) { WSADATA wSAData; uint32_t svrIp; uint16_t svrPort; SOCKET udp; uint8_t* ip = (uint8_t*)&svrIp; if (WSAStartup(0x0101, &wSAData) != 0) { // 初始化网络 printf("初始化网络出错\r\n"); return 1; } if (!getServerIp(&svrIp, &svrPort)) { // 获取物链域名服务器IP printf("获取物链域名服务器IP出错\r\n"); return 1; } printf("获取物链域名服务器IP(%d.%d.%d.%d:%d)成功\r\n", ip[0], ip[1], ip[2], ip[3], svrPort); if (argc < 3) { // 没有输入域名账号名及密码 printf("没有输入域名账号名及密码,至少需要3个参数,现在只有%d个参数\r\n", argc); return 1; } udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // 创建必要网络参数 if (udp != SOCKET_ERROR) { //创建必要网络参数 uint32_t time; char token[16]; SOCKADDR_IN addr = { 0 }; addr.sin_family = AF_INET; addr.sin_addr.s_addr = svrIp; addr.sin_port = htons(svrPort); if (LoginToServer(udp, &addr, argv[1], argv[2], token, &time)) { char outIp[16]; printf("登录物链域名服务器(token:%s 间隔时间:%d秒)成功\r\n", token, time); if (SyncHeartbeat(udp, &addr, token, outIp)) { printf("获得本机的网络IP为:%s\r\n", outIp); } } WSACleanup(); return 0; } WSACleanup(); return 1; }