您的位置:首页 > 理论基础 > 计算机网络

基于UDP的DayTime服务实现

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

服务器端代码:

#include <stdio.h>
#include <time.h>
#include <WinSock2.h>

#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 <stdio.h>
#include <WinSock2.h>

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息