I/O复用Select函数的UDP和TCP客户端和服务端

来源:互联网 发布:怎么破解积分软件 编辑:程序博客网 时间:2024/05/01 14:45

 I/O复用Select函数的UDP和TCP客户端和服务端

  •  IO复用Select函数的UDP和TCP客户端和服务端
    •  要求
    •  设计思路
    •  实验结果
      •  基本的时间传输
          •  TCP
          •  UDP
    •  体会
    •  代码
      •  服务端
      •  UDP客户端
      •  TCP客户端

 要求

- 服务端采用I/O复用模型(SELECT函数),接受客户端的时间同步请求

- 服务端采用单线程,但是要同时能够接受多个客户端的连接请求

- 服务端显示客户端的IP和端口,并回送时间信息

- 客户端包括UDP客户端和TCP客户端

 设计思路

主要是在书上的代码框架上进行修改,增加功能

- 客户端除了基本的创建套接字等步骤之外,先发送一个字符串,表示开始请求时间数据,然后就等待接收时间信息,然后修改本地时间

- 对于修改本地时间,首先要将受到的时间信息处理之后放入一个SYSTEMTIME类型的变量中,然后调用SetLocalTime()来进行修改

int set_local_time(const char *time_string){    SYSTEMTIME system_time = { 0 };    char year[4 + 1] = { 0 };    char month[2 + 1] = { 0 };    char day[2 + 1] = { 0 };    char hour[2 + 1] = { 0 };    char minute[2 + 1] = { 0 };    char second[2 + 1] = { 0 };    char Dayofweek[2] = { 0 };    char Mill[2 + 1] = { 0 };    int index = 0;    strncpy(year, time_string + index, 4);    index += 4;    strncpy(month, time_string + index, 2);    index += 2;    strncpy(Dayofweek, time_string + index, 1);    index += 1;    strncpy(day, time_string + index, 2);    index += 2;    strncpy(hour, time_string + index, 2);    index += 2;    strncpy(minute, time_string + index, 2);    index += 2;    strncpy(second, time_string + index, 2);    index += 2;    strncpy(Mill, time_string + index, 2);    index += 2;        system_time.wYear = atoi(year);    system_time.wMonth = atoi(month);    system_time.wDay = atoi(day);    system_time.wHour = atoi(hour);    system_time.wMinute = atoi(minute);    system_time.wSecond = atoi(second);    system_time.wDayOfWeek = atoi(Dayofweek);    system_time.wSecond = atoi(Mill);    SetLocalTime(&system_time);    SetLocalTime(&system_time);    if (!SetLocalTime(&system_time))    {        cout << "Set local time failed  " << WSAGetLastError()<<endl;        return -1;    }    return 0;}

- 对于TCP连接来说,在得到信息之后要断开连接,UDP不存在连接也就不需要断开

- 服务器端在发送的时候也要注意将时间数据先进行处理,以字符串的形式发送

//处理时间,将SYSTEMTIME数据处理成字符串,便于发送给客户端void get_time(){    SYSTEMTIME system_time = { 0 };    GetLocalTime(&system_time);    memset(timedata, 0sizeof(timedata));    int index = 0;    char tmp4[4];    char tmp2[2];    memset(timedata, 015);    _itoa((int)system_time.wYear, tmp4, 10);    strcat(timedata, tmp4);        _itoa((int)system_time.wMonth, tmp2, 10);    strcat(timedata, tmp2);    memset(tmp2, 0sizeof(tmp2));    _itoa((int)system_time.wDayOfWeek, tmp2, 10);    strcat(timedata, tmp2);    _itoa((int)system_time.wDay, tmp2, 10);    strcat(timedata, tmp2);    _itoa((int)system_time.wHour, tmp2, 10);    strcat(timedata, tmp2);    _itoa((int)system_time.wMinute, tmp2, 10);    strcat(timedata, tmp2);    _itoa((int)system_time.wSecond, tmp2, 10);    strcat(timedata, tmp2);    _itoa((int)system_time.wMilliseconds, tmp2, 10);    strcat(timedata, tmp2);    cout << "Server Time : "<<timedata << endl;    return;}

- 为了要能够接受TCP和UDP数据,所以在同一个端口上要同时绑定连个SOCKET

    // 为TCP套接字绑定地址和端口号    SOCKADDR_IN addrServ;    addrServ.sin_family = AF_INET;    addrServ.sin_port = htons(DEFAULT_PORT);        // 监听端口为DEFAULT_PORT    addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);    iResult = bind(TCPSocket, (const struct sockaddr*)&addrServ, sizeof(SOCKADDR_IN));    if (iResult == SOCKET_ERROR)    {        printf("bind failed with error: %d\n", WSAGetLastError());        closesocket(TCPSocket);        WSACleanup();        return 1;    }    // TCP连接监听套接字       iResult = listen(TCPSocket, SOMAXCONN);    if (iResult == SOCKET_ERROR)    {        printf("listen failed !\n");        closesocket(TCPSocket);        WSACleanup();        return -1;    }    // 为UDP套接字绑定地址和端口号    addrServ1.sin_family = AF_INET;    addrServ1.sin_port = htons(DEFAULT_PORT);        // 监听端口为DEFAULT_PORT    addrServ1.sin_addr.S_un.S_addr = htonl(INADDR_ANY);    iResult = bind(UDPSocket, (const struct sockaddr*)&addrServ1, sizeof(SOCKADDR_IN));    if (iResult == SOCKET_ERROR)    {        printf("bind failed with error: %d\n", WSAGetLastError());        closesocket(UDPSocket);        closesocket(TCPSocket);        WSACleanup();        return 1;    }    //注册TCPSOCKET和UDPSOCKET    fd_set fdRead, fdSocket;    FD_ZERO(&fdSocket);    FD_SET(TCPSocket, &fdSocket);    FD_SET(UDPSocket, &fdSocket);

- 在SELECT函数执行的过程中,如果是TCPSOCKET的连接,就将新的连接请求放入集合中,那么在后面的循环中就能处理,如果是UDPSOCKET,那么就直接用创建的UDPSOCKET和客户端进行数据通信,如果是之前的新的SOCKET连接,那就进行时间请求的通信

- 在新的TCP连接请求达到的时候,输出IP地址和端口号

//有新的连接请求                            AcceptSocket = accept(TCPSocket, (sockaddr FAR*)&addrClient, &addrClientlen);                            if (AcceptSocket == INVALID_SOCKET)                            {                                printf("accept failed !\n");                                closesocket(UDPSocket);                                closesocket(TCPSocket);                                WSACleanup();                                return 1;                            }                            //成功接收新的TCP连接                            cout << "Received time request from ( " << inet_ntoa(addrClient.sin_addr) << " :" << addrClient.sin_port << " )" << endl;

- 在接受到UDP数据的时候,显示数据来源的IP和端口号

//获取客户端的时间请求信息                        iResult = recvfrom(UDPSocket, recvbuf, recvbuflen, 0, (struct sockaddr *)&udpremote, &udpremote_len);                        if (iResult == SOCKET_ERROR || iResult == 0)                        {                            cout << "Receive time request failed " << WSAGetLastError() << endl;                            closesocket(UDPSocket);                            closesocket(TCPSocket);                            WSACleanup();                                            return -1;                        }                        recvbuf[iResult] = '\0';                        //打印UDP客户端的IP和端口信息                        cout << "Received time request from " << inet_ntoa(udpremote.sin_addr) << " :" << udpremote.sin_port << " )" << endl;

 实验结果

 基本的时间传输

 TCP

参数设置

运行结果

 UDP

参数设置

运行结果

关于本机时间修改
需要在具有管理员权限的CMD中执行,而且有时候还不管用
的确是成功修改过几次的,但是后面试的时候就再也不能成功了
具体原因也找不出来
应该是权限的问题

 体会

- 感觉将TCP和UDP的处理放在一起,对于这两个的类型的连接的处理的区别有更加深刻的印象

- 对于设置本机时间SetLocalTime,需要一定的权限,要用管理员权限的cmd,而且官方给出的建议是连续使用两次,但是实际上,还是很不稳定,有事可以成功,有时候不能

- 对于时间的处理,也要比较小心,个人感觉,如果是要将本地系统的时间修改,就需要传输所有的时间信息,而不是传输简单的年月日小时分钟秒

 代码

 服务端

// EchoTCPServer-select.cpp : 定义控制台应用程序的入口点。//#define _WINSOCK_DEPRECATED_NO_WARNINGS#define _CRT_SECURE_NO_WARNINGS#undef UNICODE #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winsock2.h> #include <ws2tcpip.h> #include <stdlib.h> #include <stdio.h> #include <iostream>#include <string.h> using namespace std;// 连接到winsock2对应的lib文件: Ws2_32.lib #pragma comment (lib, "Ws2_32.lib") #define DEFAULT_BUFLEN 512    //默认缓冲区长度为512#define DEFAULT_PORT 4000    //默认服务器端口号为27015#define MAX_LEN 1024char timedata[19] = { 0 };//处理时间,将SYSTEMTIME数据处理成字符串,便于发送给客户端void get_time(){    SYSTEMTIME system_time = { 0 };    GetLocalTime(&system_time);//    char timedata[15] = { 0 };    memset(timedata, 0sizeof(timedata));    int index = 0;    char tmp4[4];    char tmp2[2];    char tmp1;    memset(timedata, 015);    _itoa((int)system_time.wYear, tmp4, 10);    strcat(timedata, tmp4);        _itoa((int)system_time.wMonth, tmp2, 10);    strcat(timedata, tmp2);    memset(tmp2, 0sizeof(tmp2));    _itoa((int)system_time.wDayOfWeek, tmp2, 10);    strcat(timedata, tmp2);    _itoa((int)system_time.wDay, tmp2, 10);    strcat(timedata, tmp2);    _itoa((int)system_time.wHour, tmp2, 10);    strcat(timedata, tmp2);    _itoa((int)system_time.wMinute, tmp2, 10);    strcat(timedata, tmp2);    _itoa((int)system_time.wSecond, tmp2, 10);    strcat(timedata, tmp2);    _itoa((int)system_time.wMilliseconds, tmp2, 10);    strcat(timedata, tmp2);    cout << "Server Time : "<<timedata << endl;    return;}int main(int argc, char* argv[]){    WSADATA wsaData;    int iResult;    SOCKET AcceptSocket = INVALID_SOCKET;    SOCKET TCPSocket = INVALID_SOCKET;    SOCKET UDPSocket = INVALID_SOCKET;    char recvbuf[DEFAULT_BUFLEN];    int recvbuflen = DEFAULT_BUFLEN;    sockaddr_in addrClient;    int addrClientlen = sizeof(sockaddr_in);    // 初始化 Winsock     iResult = WSAStartup(MAKEWORD(22), &wsaData);    if (iResult != 0)    {        printf("WSAStartup failed with error: %d\n", iResult);        return 1;    }    // 创建用于监听的TCP套接字       TCPSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);    if (TCPSocket == INVALID_SOCKET)    {        printf("socket failed with error: %ld\n", WSAGetLastError());        WSACleanup();        return 1;    }    // 为TCP套接字绑定地址和端口号    SOCKADDR_IN addrServ;    addrServ.sin_family = AF_INET;    addrServ.sin_port = htons(DEFAULT_PORT);        // 监听端口为DEFAULT_PORT    addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);    iResult = bind(TCPSocket, (const struct sockaddr*)&addrServ, sizeof(SOCKADDR_IN));    if (iResult == SOCKET_ERROR)    {        printf("bind failed with error: %d\n", WSAGetLastError());        closesocket(TCPSocket);        WSACleanup();        return 1;    }    // TCP连接监听套接字       iResult = listen(TCPSocket, SOMAXCONN);    if (iResult == SOCKET_ERROR)    {        printf("listen failed !\n");        closesocket(TCPSocket);        WSACleanup();        return -1;    }    SOCKADDR_IN addrServ1;    // 创建用于监听的UDP套接字       UDPSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);    if (UDPSocket == INVALID_SOCKET)    {        printf("socket failed with error: %ld\n", WSAGetLastError());        closesocket(TCPSocket);        WSACleanup();        return 1;    }    // 为UDP套接字绑定地址和端口号    addrServ1.sin_family = AF_INET;    addrServ1.sin_port = htons(DEFAULT_PORT);        // 监听端口为DEFAULT_PORT    addrServ1.sin_addr.S_un.S_addr = htonl(INADDR_ANY);    iResult = bind(UDPSocket, (const struct sockaddr*)&addrServ1, sizeof(SOCKADDR_IN));    if (iResult == SOCKET_ERROR)    {        printf("bind failed with error: %d\n", WSAGetLastError());        closesocket(UDPSocket);        closesocket(TCPSocket);        WSACleanup();        return 1;    }    //注册TCPSOCKET和UDPSOCKET    fd_set fdRead, fdSocket;    FD_ZERO(&fdSocket);    FD_SET(TCPSocket, &fdSocket);    FD_SET(UDPSocket, &fdSocket);    printf("Server for TCP and UDP starting\n");    while (TRUE)    {        //通过select等待数据到达事件,如果有事件发生,select函数移除fdRead集合中没有未决I/O操作的套接字句柄,然后返回        fdRead = fdSocket;        iResult = select(0, &fdRead, NULL, NULL, NULL);        if (iResult > 0)        {            //有网络事件发生            //确定有哪些套接字有未决的I/O,并进一步处理这些I/O            for (int i = 0; i < (int)fdSocket.fd_count; i++)            {                if (FD_ISSET(fdSocket.fd_array[i], &fdRead))                {                    if (fdSocket.fd_array[i] == TCPSocket)                    {                        if (fdSocket.fd_count < FD_SETSIZE)                        {                            //同时复用的套接字数量不能大于FD_SETSIZE                            //有新的连接请求                            AcceptSocket = accept(TCPSocket, (sockaddr FAR*)&addrClient, &addrClientlen);                            if (AcceptSocket == INVALID_SOCKET)                            {                                printf("accept failed !\n");                                closesocket(UDPSocket);                                closesocket(TCPSocket);                                WSACleanup();                                return 1;                            }                            //成功接收新的TCP连接                            cout << "Received time request from ( " << inet_ntoa(addrClient.sin_addr) << " :" << addrClient.sin_port << " )" << endl;                                                        //增加新的连接套接字进行复用等待                            FD_SET(AcceptSocket, &fdSocket);                                                }                        //TCP连接数超过数量                        else                        {                            printf("Too many connect request!\n");                            continue;                        }                    }                    //UDP数据传输                    else if (fdSocket.fd_array[i] == UDPSocket)                    {                        sockaddr_in udpremote;                        int udpremote_len = sizeof(udpremote);                        //获取客户端的时间请求信息                        iResult = recvfrom(UDPSocket, recvbuf, recvbuflen, 0, (struct sockaddr *)&udpremote, &udpremote_len);                        if (iResult == SOCKET_ERROR || iResult == 0)                        {                            cout << "Receive time request failed " << WSAGetLastError() << endl;                            closesocket(UDPSocket);                            closesocket(TCPSocket);                            WSACleanup();                                            return -1;                        }                        recvbuf[iResult] = '\0';                        //打印UDP客户端的IP和端口信息                        cout << "Received time request from " << inet_ntoa(udpremote.sin_addr) << " :" << udpremote.sin_port << " )" << endl;                        //服务器获取自己的当前信息                        get_time();                                                //向UDP客户端发送时间信息                        iResult = sendto(UDPSocket, timedata, sizeof(timedata), 0, (struct sockaddr*)&udpremote, udpremote_len);                        if (iResult == SOCKET_ERROR || iResult == 0)                        {                            cout << "Return message failed with error " << WSAGetLastError() << endl;                            closesocket(UDPSocket);                            closesocket(TCPSocket);                            WSACleanup();                            return -1;                        }                        //发送成功,UDP服务完成                        cout << "Sending time to UDP Client successfully!" << endl;                        cout << "Current UDP service finished!\n\n" << endl;                    }                    else                    {                        //有TCP数据到达                        memset(recvbuf, 0, recvbuflen);                        iResult = recv(fdSocket.fd_array[i], recvbuf, recvbuflen, 0);                        if (iResult > 0)                        {                            //情况1:成功接收到数据                                                        recvbuf[iResult] = '\0';                            printf("Request received: %s\n", recvbuf);                                                    //获取本机时间                            get_time();                            int send_time;                            //向TCP客户端发送时间信息                            send_time = send(fdSocket.fd_array[i], timedata, sizeof(timedata), 0);                            if (send_time < 0)                            {                                cout << "Sending time to client failed!" << endl;                                printf("Current Connection closing...\n");                                closesocket(fdSocket.fd_array[i]);                                FD_CLR(fdSocket.fd_array[i], &fdSocket);                            }                            //发送成功,断开TCP连接                            cout << "Sending time to TCP Client successfully!" << endl;                            printf("Current TCP Connection closing...\n\n");                            closesocket(fdSocket.fd_array[i]);                            FD_CLR(fdSocket.fd_array[i], &fdSocket);                        }                        else if (iResult == 0)                        {                            //情况2:连接关闭                            printf("Current Connection closing...\n");                            closesocket(fdSocket.fd_array[i]);                            FD_CLR(fdSocket.fd_array[i], &fdSocket);                        }                        else                        {                            //情况3:接收失败                            printf("recv failed with error: %d\n", WSAGetLastError());                            closesocket(fdSocket.fd_array[i]);                            FD_CLR(fdSocket.fd_array[i], &fdSocket);                        }                    }                }                            }        }        else        {            printf("select failed with error: %d\n", WSAGetLastError());            break;        }    }    // cleanup     closesocket(UDPSocket);    closesocket(TCPSocket);    WSACleanup();    return 0;}

 UDP客户端

#define _WINSOCK_DEPRECATED_NO_WARNINGS#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <stdlib.h>#include <stdio.h>#include <winsock2.h>#include <WS2tcpip.h>//#include <winsock.h>#pragma comment (lib,"ws2_32.lib")using namespace std;#define  MAX_LEN 1024//设置本地时间,调用SetLocalTime(&system_time),要使用管理者身份运行,最好调用两次,为了保险,我调用了三次int set_local_time(const char *time_string){    SYSTEMTIME system_time = { 0 };    char year[4 + 1] = { 0 };    char month[2 + 1] = { 0 };    char day[2 + 1] = { 0 };    char hour[2 + 1] = { 0 };    char minute[2 + 1] = { 0 };    char second[2 + 1] = { 0 };    char Dayofweek[2] = { 0 };    char Mill[2 + 1] = { 0 };    int index = 0;    strncpy(year, time_string + index, 4);    index += 4;    strncpy(month, time_string + index, 2);    index += 2;    strncpy(Dayofweek, time_string + index, 1);    index += 1;    strncpy(day, time_string + index, 2);    index += 2;    strncpy(hour, time_string + index, 2);    index += 2;    strncpy(minute, time_string + index, 2);    index += 2;    strncpy(second, time_string + index, 2);    index += 2;    strncpy(Mill, time_string + index, 2);    index += 2;    system_time.wYear = atoi(year);    system_time.wMonth = atoi(month);    system_time.wDay = atoi(day);    system_time.wHour = atoi(hour);    system_time.wMinute = atoi(minute);    system_time.wSecond = atoi(second);    system_time.wDayOfWeek = atoi(Dayofweek);    system_time.wSecond = atoi(Mill);    SetLocalTime(&system_time);    SetLocalTime(&system_time);    if (SetLocalTime(&system_time) == 0)    {        cout << "Set local time failed!" << endl;        return -1;    }    return 0;}int __cdecl main(int argc, char* argv[]){    WSADATA ws;    SOCKET ConnectSocket = INVALID_SOCKET;    struct sockaddr_in Server_addr;    int iResult = 0;    int Addrlen = 0;    HANDLE hThread = NULL;    char Sendbuffer[MAX_LEN] = "Ask time information";    char Recvbuffer[MAX_LEN];    SYSTEMTIME system_time = { 0 };    //check parameters    if (argc != 3)    {        cout << "Need target IP and port !" << endl;        return -1;    }    int PORT = atoi(argv[2]);    //Initiate socket    iResult = WSAStartup(MAKEWORD(22), &ws);    if (iResult != 0)    {        cout << "Initiate failed with error: " << GetLastError() << endl;        return -1;    }    //Create socket    ConnectSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);    if (ConnectSocket == INVALID_SOCKET)    {        cout << "Create Client socket failed with error: " << WSAGetLastError() << endl;        WSACleanup();        return -1;    }    Server_addr.sin_family = AF_INET;    Server_addr.sin_addr.s_addr = inet_addr(argv[1]);    Server_addr.sin_port = htons(PORT);    memset(Server_addr.sin_zero, 0x008);    int Server_len = sizeof(Server_addr);        //发送请求        iResult = sendto(ConnectSocket, Sendbuffer, strlen(Sendbuffer), 0, (sockaddr *)&Server_addr, Server_len);    if (iResult != strlen(Sendbuffer) && iResult != MAX_LEN)    {        cout << "Sending failed with error :" << WSAGetLastError() << endl;        cout << "Client exit." << endl;        closesocket(ConnectSocket);        WSACleanup();        return -1;    }    else    {        cout << "Asking time information successfully!" << endl;    }    sockaddr_in remote;    int remote_len = sizeof(remote);    //获取时间信息    iResult = recvfrom(ConnectSocket, Recvbuffer, MAX_LEN, 0, (struct sockaddr *)&remote, &remote_len);    if (iResult == SOCKET_ERROR || iResult == 0)    {        cout << "Get time information for server failed!" << endl;        cout << "Connection close!" << "\n\n" << endl;        closesocket(ConnectSocket);        WSACleanup();        return -1;    }    else    {        cout << "Receive time data from server : " << Recvbuffer << endl;        //获取服务器时间信息之间的本地时间        GetLocalTime(&system_time);        printf("\nPrevious Time : %04u-%02u-%02u  %02u:%02u:%02u\n\n", system_time.wYear, system_time.wMonth, system_time.wDay, system_time.wHour, system_time.wMinute, system_time.wSecond);        //根据服务器返回信息修改本机时间        set_local_time(Recvbuffer);        //获取服务器时间信息之间的本地时间        GetLocalTime(&system_time);        printf("\nPresent Time : %04u-%02u-%02u  %02u:%02u:%02u\n\n", system_time.wYear, system_time.wMonth, system_time.wDay, system_time.wHour, system_time.wMinute, system_time.wSecond);    }    closesocket(ConnectSocket);    WSACleanup();    system("pause");    return 0;}

 TCP客户端

#define _WINSOCK_DEPRECATED_NO_WARNINGS#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <stdlib.h>#include <stdio.h>#include <winsock2.h>#include <winbase.h>#pragma comment (lib,"ws2_32.lib")#pragma comment (lib,"kernel32.lib")using namespace std;#define  MAX_LEN 1024//#define PORT 4000//#define TARGET_IP "127.0.0.1"//#define TARGET_IP "192.168.56.102"//设置本地时间,调用SetLocalTime(&system_time),要使用管理者身份运行,最好调用两次,为了保险,我调用了三次int set_local_time(const char *time_string){    SYSTEMTIME system_time = { 0 };    char year[4 + 1] = { 0 };    char month[2 + 1] = { 0 };    char day[2 + 1] = { 0 };    char hour[2 + 1] = { 0 };    char minute[2 + 1] = { 0 };    char second[2 + 1] = { 0 };    char Dayofweek[2] = { 0 };    char Mill[2 + 1] = { 0 };    int index = 0;    strncpy(year, time_string + index, 4);    index += 4;    strncpy(month, time_string + index, 2);    index += 2;    strncpy(Dayofweek, time_string + index, 1);    index += 1;    strncpy(day, time_string + index, 2);    index += 2;    strncpy(hour, time_string + index, 2);    index += 2;    strncpy(minute, time_string + index, 2);    index += 2;    strncpy(second, time_string + index, 2);    index += 2;    strncpy(Mill, time_string + index, 2);    index += 2;    system_time.wYear = atoi(year);    system_time.wMonth = atoi(month);    system_time.wDay = atoi(day);    system_time.wHour = atoi(hour);    system_time.wMinute = atoi(minute);    system_time.wSecond = atoi(second);    system_time.wDayOfWeek = atoi(Dayofweek);    system_time.wSecond = atoi(Mill);    SetLocalTime(&system_time);    SetLocalTime(&system_time);    if (!SetLocalTime(&system_time))    {        cout << "Set local time failed  " << WSAGetLastError()<<endl;        return -1;    }    return 0;}int __cdecl main(int argc, char* argv[]){    WSADATA ws;    SOCKET ConnectSocket = INVALID_SOCKET;    struct sockaddr_in Server_addr;    int iResult = 0;    int Addrlen = 0;    HANDLE hThread = NULL;    char Sendbuffer[MAX_LEN] ="Ask time information";    char Recvbuffer[MAX_LEN];    SYSTEMTIME system_time = { 0 };    //check parameters    if (argc != 3)    {        cout << "Need target IP and port !" << endl;        return -1;    }    int PORT = atoi(argv[2]);    //Initiate socket    iResult = WSAStartup(MAKEWORD(22), &ws);    if (iResult != 0)    {        cout << "Initiate failed with error: " << GetLastError() << endl;        return -1;    }    //Create socket    ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    if (ConnectSocket == INVALID_SOCKET)    {        cout << "Create Client socket failed with error: " << WSAGetLastError() << endl;        WSACleanup();        return -1;    }    Server_addr.sin_family = AF_INET;    Server_addr.sin_addr.s_addr = inet_addr(argv[1]);    Server_addr.sin_port = htons(PORT);    memset(Server_addr.sin_zero, 0x008);    iResult = connect(ConnectSocket, (struct sockaddr*)&Server_addr, sizeof(Server_addr));    if (iResult != 0)    {        cout << "Connect with error: " << WSAGetLastError() << endl;        WSACleanup();        return -1;    }    else    {        cout << "Connect successfully!" << endl;    }    //发送请求        iResult = send(ConnectSocket, Sendbuffer, strlen(Sendbuffer), 0);    if (iResult == strlen(Sendbuffer))    {        cout << "Asking time information from server!" << endl;    }    else    {        cout << "Asking time information failed!" << endl;        cout << "Ready to exit\n" << endl;        closesocket(ConnectSocket);        WSACleanup();        return -1;    }    //获取时间信息    memset(Recvbuffer, 0sizeof(Recvbuffer));    iResult = recv(ConnectSocket, Recvbuffer, sizeof(Recvbuffer), 0);    if (iResult < 0)    {        cout << "Get time information for server failed!" << endl;        cout << "Connection close!" << "\n\n" << endl;    }    else    {        cout << "Receive time data from server : " << Recvbuffer << endl;        //获取服务器时间信息之间的本地时间        GetLocalTime(&system_time);        printf("\nPrevious Time : %04u-%02u-%02u  %02u:%02u:%02u\n\n", system_time.wYear, system_time.wMonth, system_time.wDay, system_time.wHour, system_time.wMinute, system_time.wSecond);                //根据服务器返回信息修改本机时间        set_local_time(Recvbuffer);        //获取服务器时间信息之间的本地时间        GetLocalTime(&system_time);        printf("\nPresent Time : %04u-%02u-%02u  %02u:%02u:%02u\n\n", system_time.wYear, system_time.wMonth, system_time.wDay, system_time.wHour, system_time.wMinute, system_time.wSecond);    }    closesocket(ConnectSocket);    WSACleanup();    system("pause");    return 0;}
0 0