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
- Socket编程 ——I/O复用(时间请求)
- Socket编程 —I/O复用的时间请求
- Socket编程:I/O复用
- I/O Socket编程
- Socket编程之I/O复用
- Socket编程实践 -- Select I/O复用
- 深入研究socket编程(6)——高级I/O复用(select、poll 、 epoll)
- socket编程:I/O模型
- Socket编程实践(8) --Select-I/O复用
- Socket编程实践(7) --Select-I/O复用
- Socket编程实践(8) --Select-I/O复用
- 深入研究socket编程(5)——I/O复用的高级应用
- linux下socket编程:I/O模型
- socket编程中的I/O模型
- socket的I/O复用
- Linux 高性能服务器编程——I/O复用
- Linux高性能服务器编程——I/O复用
- Linux高性能服务器编程——I/O复用
- Android 工程项目改名[Eclipse]
- Memcached概念、作用、运行原理、特性、不足简单梳理
- git中配置使用BCompare工具
- ODBC链接
- 使用Hibernate框架的demo--打印数据库信
- Socket编程 ——I/O复用(时间请求)
- C语言CGI实现文件上传
- 让你的「微信小程序」运行在Chrome浏览器上
- Docker搭建gitlab服务器让GitLab安装部署更简
- Java实现(08)——过滤器模式(Filter Pattern)
- 键盘方法论: 在键盘前面,你就是钢琴师!
- 基于yeoman定制的交互式命令行脚手架
- 从All-In-One到SOA——技术及架构的演进过
- 掌握css3布局