基于UDP的DayTime服务实现

DayTime服务是一个有用的调试工具,它的作用就是返回当前时间和日期,格式是字符串格式。下面是笔者在学习套接字编程时自己实现的DayTime服务代码,和大家分享一下,权当是抛砖引玉吧。
服务器端代码:
#include 
#include 
#include 

#pragma comment (lib,"ws2_32.lib")

//DayTime协议默认端口为13
#define DAYTIME_DEF_PORT   13
//缓冲区大小设置为256
#define DAYTIME_BUF_SIZE   256

int main(void)
{
	/**********************************************************************************/
	//1.数据定义与初始化操作
	/**********************************************************************************/
	WSADATA wsaData;
	//定义DayTime套接字句柄
	SOCKET serv_sock = 0;
	//sockaddr_in为IPv4协议的socket结构
	struct sockaddr_in serv_addr, clnt_addr;
	int result, addr_len = sizeof(serv_addr);
	//默认情况将目的地址设为本地环回地址
	char *time_str, recv_buf[DAYTIME_BUF_SIZE];
	time_t now_time;
	WSAStartup(MAKEWORD(2,2), &wsaData);
	//服务器地址(协议、端口、IP)
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(DAYTIME_DEF_PORT);
	serv_addr.sin_addr.s_addr = INADDR_ANY;

	/**********************************************************************************/
	//2.设置接收数据包的套接字
	/**********************************************************************************/
	serv_sock = socket(AF_INET, SOCK_DGRAM, 0);
	if ( serv_sock == INVALID_SOCKET )
	{
		printf("[DayTime] create error : %d\n",WSAGetLastError());
		WSACleanup();
		return -1;
	}
	
	/**********************************************************************************/
	//2.绑定套接字到本地
	/**********************************************************************************/
	result = bind(serv_sock, (struct sockaddr*)&serv_addr, addr_len);
	if (result == SOCKET_ERROR)
	{
		printf("[DayTime] bind error : %d", WSAGetLastError());
		closesocket(serv_sock);
		return -1;
	}

	printf("[DayTime] The serve is running ... ...\r\n");
	/**********************************************************************************/
	//3.发送和接收数据
	/**********************************************************************************/
	while(1)
	{
		result = recvfrom(serv_sock, recv_buf, DAYTIME_BUF_SIZE, 0,
			(struct sockaddr*)&clnt_addr, &addr_len);
		if (result == SOCKET_ERROR)
		{
			printf("[DayTime] recv error : %d\n", WSAGetLastError());
			closesocket(serv_sock);
			WSACleanup();
			return -1;
		}
		//成功调用后,返回至result为发送数据字节数,下语句是为字符串加上终止符
		recv_buf[result] = '\0';
		printf("[DayTime] recv: \"%s\", from %s\r\n", recv_buf, inet_ntoa(clnt_addr.sin_addr));
		now_time = time(0);
		time_str = ctime(&now_time);
		//将字符串最后换行符替换成结束符,便于进行输出控制
		time_str[strlen(time_str)-1] = '\0';
		sendto(serv_sock, time_str, strlen(time_str), 0, (struct sockaddr*)&clnt_addr, addr_len);
		if (result == SOCKET_ERROR)
		{
			printf("[DayTime] send error : %d\n", WSAGetLastError());
			closesocket(serv_sock);
			WSACleanup();
			return -1;
		}
	}

	/**********************************************************************************/
	//7.回收资源
	/**********************************************************************************/
	closesocket(serv_sock);
	WSACleanup();

	return 0;
}

客户端代码:
#include 
#include 

#pragma comment(lib,"ws2_32.lib")

//DayTime协议默认端口为13
#define DAYTIME_DEF_PORT   13
//缓冲区大小设置为256
#define DAYTIME_BUF_SIZE   256
//发送次数设置为3次
#define DAYTIME_DEF_COUNT  3

int main(int argc, char** argv)
{
	/**********************************************************************************/
	//1.数据定义与初始化操作
	/**********************************************************************************/
	WSADATA wsaData;
	//定义DayTime套接字句柄
	SOCKET time_sock = 0;
	//sockaddr_in为IPv4协议的socket结构
	struct sockaddr_in peer_addr, serv_addr;
	//设置接收超时,3秒
	int timeout = 3000;
	int i, result, send_len, addr_len = sizeof(serv_addr);
	//默认情况将目的地址设为本地环回地址
	char *dest = "127.0.0.1", *send_data = "DayTime Test";
	char recv_buf[DAYTIME_BUF_SIZE];
	send_len = strlen(send_data);
	WSAStartup(MAKEWORD(2,2), &wsaData);
	//根据命令行参数,设置服务器IP
	if (argc == 2)
		dest = argv[1];
	//服务器地址(协议、端口、IP)
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(DAYTIME_DEF_PORT);
	serv_addr.sin_addr.s_addr = inet_addr(dest);
	if (serv_addr.sin_addr.s_addr == INADDR_NONE)
	{
		printf("[DayTime] invalid address\r\n");
		return -1;
	}

	/**********************************************************************************/
	//2.设置发送数据包的套接字
	/**********************************************************************************/
	time_sock = socket(AF_INET, SOCK_DGRAM, 0);
	if ( time_sock == INVALID_SOCKET )
	{
		printf("[DayTime] create error : %d\n",WSAGetLastError());
		WSACleanup();
		return -1;
	}

	/**********************************************************************************/
	//3.设置套接字选项
	/**********************************************************************************/
	result = setsockopt(time_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));

	/**********************************************************************************/
	//4.发送和接收数据
	/**********************************************************************************/
	for (i = 0; i < DAYTIME_DEF_COUNT; i++)
	{
		//发送数据包
		result = sendto(time_sock, send_data, send_len, 0,
			(struct sockaddr*)&serv_addr, sizeof(serv_addr));
		if (result == SOCKET_ERROR)
		{
			printf("[DayTime] send error : %d\n", WSAGetLastError());
			closesocket(time_sock);
			WSACleanup();
			return -1;
		}
		//等待接收数据包,等待时间上限为timeout
		result = recvfrom(time_sock, recv_buf, DAYTIME_BUF_SIZE, 0,
			(struct sockaddr*)&peer_addr, &addr_len);
		if (result == SOCKET_ERROR)
		{
			printf("[DayTime] recv error : %d\n", WSAGetLastError());
			closesocket(time_sock);
			WSACleanup();
			return -1;
		}
		//成功调用后,返回至result为发送数据字节数,下语句是为字符串加上终止符
		recv_buf[result] = '\0';
		printf("[DayTime] recv: \"%s\", from %s\n",recv_buf, inet_ntoa(peer_addr.sin_addr));
	}

	/**********************************************************************************/
	//7.回收资源
	/**********************************************************************************/
	closesocket(time_sock);
	WSACleanup();

	return 0;
}


你可能感兴趣的:(网络编程)