Socket编程 ——I/O复用(时间请求)

来源:互联网 发布:德州扑克 技巧 知乎 编辑:程序博客网 时间:2024/05/21 22:56

一 实验内容

利用I/O复用模型实现一个时间同步服务器
1. 服务端采用I/O复用模型(select函数)接收客户端的时间同步请求;
服务端采用单线程,但要能同时接收多客户端的连接请求,显示客户端IP
2. 和端口,并向其回送时间信息。
3. 客户端尝试同时使用UDP和TCP来实现。
注:借助I/O复用模型,用单线程达到多线程的效果。

二 代码设计

Client
时间同步函数

SYSTEMTIME curtime;//声明结构体变量;curtime.wHour = hour;curtime.wMinute = min;curtime.wSecond = sec;//结构体变量curtime各项值别赋值if (SetLocalTime(&curtime)){    cout << "yes";}else{    cout << "no";}

TCP

//从服务器接受时间并输出while (true){    cin >> SendBuffer;    Ret = send(ClientSocket, SendBuffer, (int)strlen(SendBuffer), 0);    if (Ret == SOCKET_ERROR)    {        cout << "Send Info Error::" << GetLastError() << endl;        break;    }    Ret = recv(ClientSocket,(char *)&hour , 4, 0);    Ret = recv(ClientSocket, (char *)&min, 4, 0);    Ret = recv(ClientSocket, (char *)&sec, 4, 0);    cout << hour << min <<sec<<endl;}

UDP

//从服务器接受时间并输出while (1){    cin >> sendData;    sendto(sclient, sendData, strlen(sendData), 0, (sockaddr *)&sin, len);    char recvData[255];    int ret = recvfrom(sclient, (char *)&hour, 4, 0, (sockaddr *)&sin, &len);    ret = recvfrom(sclient, (char *)&min, 4, 0, (sockaddr *)&sin, &len);    ret = recvfrom(sclient, (char *)&sec, 4, 0, (sockaddr *)&sin, &len);    if (ret > 0)    {        cout << hour << min << sec << endl;    }}

Server

// 创建用于监听的套接字       ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);//TCP监听套接字    UDPSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);//UDP套接字
//为两个套接字绑定同一个端口addrServ.sin_family = AF_INET;addrServ.sin_port = htons(DEFAULT_PORT);        // 监听端口为DEFAULT_PORTaddrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);iResult1 = bind(ServerSocket, (const struct sockaddr*)&addrServ, sizeof(SOCKADDR_IN));iResult2 = bind(UDPSocket, (const struct sockaddr*)&addrServ, sizeof(SOCKADDR_IN));
//将绑定过端口的套接字加入套接字集合fdSocket中,可以观察到TCP监听套接字在[0]中,UDP套接字在[1]中fd_set fdRead, fdSocket;FD_ZERO(&fdSocket);FD_SET(ServerSocket, &fdSocket);FD_SET(UDPSocket, &fdSocket);
//用select函数挑选有响应的套接字fdRead = fdSocket;iResult = select(0, &fdRead, NULL, NULL, NULL);
//向集合中添加新socketif (fdSocket.fd_array[i] == ServerSocket){    if (fdSocket.fd_count < FD_SETSIZE)    {        //同时复用的套接字数量不能大于FD_SETSIZE        //有新的连接请求        AcceptSocket = accept(ServerSocket, (sockaddr FAR*)&addrClient, &addrClientlen);        if (AcceptSocket == INVALID_SOCKET)        {            printf("accept failed !\n");            closesocket(ServerSocket);            WSACleanup();            return 1;        }        //增加新的连接套接字进行复用等待        FD_SET(AcceptSocket, &fdSocket);        printf("接收到新的连接:%s\n", inet_ntoa(addrClient.sin_addr));    }    else    {        printf("连接个数超限!\n");        continue;    }}

发送数据阶段

//tcp数据处理if (i != 1){    memset(recvbuf, 0, recvbuflen);    now = time(NULL);    tm = localtime(static_cast<const time_t*>(&now));    hour = tm->tm_hour;    min = tm->tm_min;    sec = tm->tm_sec;    //获取时间并传送    iResult = recv(fdSocket.fd_array[i], recvbuf, recvbuflen, 0);    Ret = send(fdSocket.fd_array[i], (const char *)&hour, 4, 0);    Ret = send(fdSocket.fd_array[i], (const char *)&min, 4, 0);    Ret = send(fdSocket.fd_array[i], (const char *)&sec, 4, 0);    if (Ret == SOCKET_ERROR)    {        cout << "Send Info Error::" << GetLastError() << endl;        break;            }}
//udp数据处理char recvData[255];    int ret = recvfrom(UDPSocket, recvData, 255, 0, (sockaddr *)&remoteAddr, &nAddrLen);    if (ret > 0)    {        recvData[ret] = 0x00;    }    //        char * sendData = "一个来自服务端的UDP数据包\n";      now = time(NULL);    tm = localtime(static_cast<const time_t*>(&now));    hour = tm->tm_hour;    min = tm->tm_min;    sec = tm->tm_sec;    //获取时间并传送    sendto(fdSocket.fd_array[i], (const char *)&hour, 4, 0, (sockaddr *)&remoteAddr, nAddrLen);    sendto(fdSocket.fd_array[i], (const char *)&min, 4, 0, (sockaddr *)&remoteAddr, nAddrLen);    sendto(fdSocket.fd_array[i], (const char *)&sec, 4, 0, (sockaddr *)&remoteAddr, nAddrLen);    cout << "UDP时间发送成功!";

三 实验实现

UDP Client测试
这里写图片描述
TCP Client测试
这里写图片描述
TCP / UDP Client测试
这里写图片描述
修改时间成功
服务器的时间设为2013.5.5 5:17 此时客户端更改时间为下图

这里写图片描述

0 0
原创粉丝点击