利用I/O复用模型实现一个时间同步服务器

I/O-Server


#include "stdafx.h"
#include <time.h>
#include <windows.h>
#include "SocketFrame.h"

#define ECHOPORT "1234"   //默认端口1234

int recvn(SOCKET s, char* recvbuf, unsigned int fixedlen)
{
	int iResult;
	int cnt;
	cnt = fixedlen;
	while ( cnt > 0 ) 
	{
		iResult = recv(s, recvbuf, cnt, 0);
		if ( iResult < 0 )
		{
			printf("Recieve error : %d\n", WSAGetLastError());
			WSAGetLastError() << endl;
			system("pause");
			closesocket(s);
			WSACleanup();
			return -1;
		}
		if ( iResult == 0 )
		{
			printf("connection closed!\n");
			system("pause");
			closesocket(s);
			WSACleanup();
			return fixedlen - cnt;
		}
		//printf("recieved byte : %d\n", iResult);
		recvbuf +=iResult;
		cnt -=iResult;         
	}
	return fixedlen;
}

//获取本机时间
void gettime(char sendbuf[])
{											
	time_t rawtime;
	struct tm * timeinfo;
  
	time (&rawtime);
	timeinfo = localtime (&rawtime);
	strftime (sendbuf,80,"%Y/%m/%d %X",timeinfo);						//strftime函数可以指定输出时间的格式
}

int main(int argc, char* argv[])
{
	CSocketFrame frame;
	int iresult=0;
	char recvbuf[MAXLINE],sendbuf[MAXLINE];
	SOCKET listensocket,connectsocket,serversocket;
	struct sockaddr_in cliaddr;
	int addrlen=sizeof(sockaddr_in);
	frame.start_up();
	listensocket = frame.tcp_server(NULL,ECHOPORT);									//创建TCP的套接字并绑定
	if(listensocket==-1)
		return -1;  
	//设置端口可重用
	int on=true;
	iresult=setsockopt(listensocket,SOL_SOCKET,SO_REUSEADDR,(char *)&on,sizeof(on));
	if(iresult==SOCKET_ERROR){
		frame.quit(listensocket);
		return -1;
	}
	serversocket = frame.udp_server(NULL,ECHOPORT);									//创建UDP的套接字并绑定
	if(serversocket==-1)
		return -1;
	printf("=========================== Server is start now! =============================\n");
	fd_set fdread,fdsocket;
	FD_ZERO(&fdsocket);																
	FD_SET(serversocket,&fdsocket);
	FD_SET(listensocket,&fdsocket);
	//通过select等待数据到达事件
	while(true)
	{																					
																						//如果有事件发生,select()移除fdread集合中没有未决I/O操作的套接字,然后返回																		
		fdread=fdsocket;
		iresult=select(0,&fdread,NULL,NULL,NULL);
		if(iresult>0)																	//iresult大于0,表示有网络事件发生
		{																
																						//确定有哪些套接字由未决的I/O并进行处理								
			for(int i=0;i<(int)fdsocket.fd_count;i++)
			{
				if(FD_ISSET(fdsocket.fd_array[i],&fdread))								//接收到TCP请求
				{								
					if(fdsocket.fd_array[i]==listensocket)
					{
						printf("\n------------------------------------------------------------------------------\n");
						printf("Receive a TCP request for getting time !\n");
						if(fdsocket.fd_count<FD_SETSIZE)								//能够复用的套接字有限,故不能超出最大数量
						{								
							connectsocket=accept(listensocket,(sockaddr FAR *)&cliaddr,&addrlen); //接收连接请求
							if(connectsocket==INVALID_SOCKET)
							{
								printf("accept failed!\n");
								closesocket(listensocket);
								WSACleanup();
								return 1;
							}
							FD_SET(connectsocket,&fdread);								//同时增加新的套接字进行复用等待新的连接
							printf("a new one connect : %s ; %d\n\n",inet_ntoa(cliaddr.sin_addr),(cliaddr.sin_port));
							iresult=recv(connectsocket,recvbuf,MAXLINE,0);
							if (iresult == -1 )
							{
								printf("Recieve Failed!!!\n");
								closesocket(connectsocket);
								continue;
							}
							gettime(sendbuf);                                          //获取本机时间
							printf("server time : %s\n",sendbuf);
							DWORD temp= htonl(strlen(sendbuf));								//先发送长度,再发送内容,便于客户端准确接收
							iresult=send(connectsocket, (char *)&temp, sizeof(DWORD), 0);	
							if (iresult==SOCKET_ERROR)									
							{ 
								printf("send failed with error: %d\n", WSAGetLastError()); 
								closesocket(connectsocket);
								continue;
							}
							iresult=send(connectsocket,sendbuf,strlen(sendbuf),0);			//发送具体的时间
							if (iresult==SOCKET_ERROR)									
							{ 
								printf("send failed with error: %d\n", WSAGetLastError()); 
								closesocket(connectsocket);
								continue;
							}
							printf("send time success!\n");
						}	
						else
						{															//连接个数过多!
							printf("too many!\n");
							continue;
							}
						printf("------------------------------------------------------------------------------\n\n");
						}
					else if(fdsocket.fd_array[i]==serversocket)										//接收到UDP协议的数据
					{								
						memset(recvbuf,0,MAXLINE);
						iresult=recvfrom(fdsocket.fd_array[i],recvbuf,MAXLINE,0,(sockaddr *)&cliaddr,&addrlen); //接收数据
						printf("\n------------------------------------------------------------------------------\n");
						printf("Receive a UDP request for getting time !\n");
						if(iresult>0)
						{
							gettime(sendbuf);													//获取本机时间
							printf("server time : %s\n",sendbuf);												
							iresult=sendto(fdsocket.fd_array[i],sendbuf,strlen(sendbuf),0,(sockaddr *)&cliaddr,addrlen);//将时间直接发送给客户端
							if(iresult==SOCKET_ERROR)
							{
								printf("sendto error : %ld\n",WSAGetLastError());
								closesocket(fdsocket.fd_array[i]);
								FD_CLR(fdsocket.fd_array[i],&fdsocket);
							}
							else printf("send time success!\n");

						}
						else if(iresult == 0)
						{
							printf("connection closed!\n");
							closesocket(fdsocket.fd_array[i]);
							FD_CLR(fdsocket.fd_array[i],&fdsocket);
						}
						else
						{
							printf("recieve error!\n");
							closesocket(fdsocket.fd_array[i]);
							FD_CLR(fdsocket.fd_array[i],&fdsocket);
						}
						printf("------------------------------------------------------------------------------\n\n");
					}
				}
			}
		}
		else 
		{
			printf("select error : %d\n",WSAGetLastError());
			break;
		}
	}
	closesocket(serversocket);
	frame.quit(listensocket);
	return 0;
}




TCP_Client


#include "stdafx.h"
#undef UNICODE 
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

#define MaxSize 1024

const char *SeverIp = "127.0.0.1";
HANDLE temphandle;

int recvn(SOCKET s, char* recvbuf, unsigned int fixedlen)
{
	int iResult;
	int cnt;
	cnt = fixedlen;
	while ( cnt > 0 ) 
	{
		iResult = recv(s, recvbuf, cnt, 0);
		if ( iResult < 0 )
		{
			printf("Recieve error : %d\n", WSAGetLastError());
			WSAGetLastError() << endl;
			system("pause");
			closesocket(s);
			WSACleanup();
			return -1;
		}
		if ( iResult == 0 )
		{
			printf("connection closed!\n");
			system("pause");
			closesocket(s);
			WSACleanup();
			return fixedlen - cnt;
		}
		//printf("recieved byte : %d\n", iResult);
		recvbuf +=iResult;
		cnt -=iResult;         
	}
	return fixedlen;
}

int main(int argc, char* argv[])
{
	WSADATA wsaData;
	int iresult;
	iresult = WSAStartup(MAKEWORD(2,2),&wsaData);
	if (iresult!=0)
	{
		printf("WSAStartup failed with error: %d\n", iresult);
        return 1;
	}

	if (LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
	{
		WSACleanup();
		return 0;
	}
	SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);
	SOCKADDR_IN addrSrv;
	addrSrv.sin_addr.S_un.S_addr=inet_addr(SeverIp);
	addrSrv.sin_family=AF_INET;
	addrSrv.sin_port=htons(1234);
	while(true)
	{									//不停的向服务端发起连接,直至连接成功在开始正常工作
		iresult = connect(sockClient,(struct sockaddr*)&addrSrv, sizeof(sockaddr));
		if (iresult!= SOCKET_ERROR) break;	
	}
	printf("connect success!\n");
	char sendbuf[MaxSize]="hello",revbuf[MaxSize]="",len[5]=""; 
	printf("Press any key to get the server time .\n");	
	getchar();												//按任意键向服务端发送“hello”
	iresult=send(sockClient,sendbuf,strlen(sendbuf),0);		
	if (iresult==SOCKET_ERROR)
	{
		printf("send iresult:%d\n",WSAGetLastError());
		printf("Exiting....................\n");
		closesocket(sockClient);
		return 0;
	}
	int cnt=0;
	unsigned int reclen;
	iresult = recvn(sockClient,(char *)&reclen,sizeof( unsigned int ));   //先接收时间信息的长度
	if (iresult==-1)
		{
			printf("Lose connection server!\n\n\n");
			closesocket(sockClient);
			WSACleanup();
			return 0;
		}
	reclen = ntohl(reclen);
	//printf("%d\n",reclen);
	iresult=recvn(sockClient,revbuf,reclen);					//根据长度接收时间信息,然后打印出来
	if(iresult<=0){
		printf("recieve error!\nlose connection....................\n");
		closesocket(sockClient);
		return 0;
	}
	revbuf[iresult]='\0';
	printf("recieve success!\nserver time is : %s",revbuf);
	closesocket(sockClient);
	Sleep(10000);
    WSACleanup();
	return 0;
}


UDP_Client


#include "stdafx.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

#define MaxSize 1024
#define DEFAULT_PORT "1234"

const char *SeverIp = "127.0.0.1";

int main(int argc, char* argv[])
{
    WORD socketVersion = MAKEWORD(2,2);
    WSADATA wsaData;
	int error;
	char sendbuff[MaxSize]="hello";
	char recvbuff[MaxSize];
	error=WSAStartup(socketVersion, &wsaData);
    if(error!= 0)
    {
		printf("WSAStartup failed with error: %d\n", error);
        return 0;
    }
    SOCKET clientsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(1234);
    sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    int len = sizeof(sin);
	printf("Press any key to get the server time .\n");			//按任意键向服务器发送"hello"
	getchar();
	sendto(clientsocket, sendbuff, strlen(sendbuff), 0, (sockaddr *)&sin, len);
	error = recvfrom(clientsocket, recvbuff, 255, 0, (sockaddr *)&sin, &len);//直接接受服务器的时间信息,然后打印出来
	if(error > 0)
	{
		recvbuff[error] = 0x00;
		printf("recieve success!\nserver time is : %s",recvbuff);
		puts("");
	}
    closesocket(clientsocket);
	Sleep(10000);
    WSACleanup();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值