您的位置:首页 > 其它

一对经典的时间获取客户/服务器程序

2014-02-22 09:10 260 查看
前言

  本文通过一对经典的时间获取客户/服务器程序,展现了Linux网络编程的大体框架,为以后更深入的学习打下基础。

客户服务器模式网络编程的大体框架



客户端代码

#include <stdio.h>
// 下头文件包含socket(), bind()等套接字通信必须的函数。
#include <sys/socket.h>
// 下头文件包含网际套接字变量的类型定义等。
#include <netinet/in.h>
// 下头文件包含bzero()函数等
#include <string.h>
// 下头文件包含errno变量等
#include <errno.h>

#define MAXLINE 100

int main (int argc, char ** argv)
{
// 定义套接字描述符变量sockfd
// 定义变量n存放read函数返回值
int sockfd, n;
// 定义字符数组recvline存放时间查询结果
char recvline[MAXLINE + 1];
// 定义套接字变量servaddr( 注意这里存放的是服务器端的信息 )
struct sockaddr_in servaddr;

// 检查命令格式是否正确
if (argc != 2) {
puts("命令格式错误\n");
return 1;
}

// 创建一个网际字节流套接字
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) <0) {
puts("网际套接字创建失败\n");
return 2;
}

// 将套接字变量servaddr清零
bzero(&servaddr, sizeof(servaddr));
// 给套接字变量的协议段赋值( AF_INET表示IPv4协议 )
servaddr.sin_family = AF_INET;
// 给套接字变量的端口段赋值( 13是时间服务器端口 )
servaddr.sin_port = htons(13);
// 给套接字变量的IP段赋值( argv[1]存放服务器IP )
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
puts("IP地址格式转换失败");
return 3;
}

// 按照先前socket函数指定的协议类型与服务器进行连接
if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
puts("连接失败\n");
return 4;
}

// 从缓冲区读取时间查询结果并放进recvline数组中
if ( (n = read(sockfd, recvline, MAXLINE)) > 0 ) {
recvline
= 0;
puts(recvline);
}
if (n < 0) {
puts("读取数据发生错误");
}

return 0;
}


服务器端代码

#include <stdio.h>

// 下头文件包含socket(), bind()等套接字通信必须的函数。
#include <sys/socket.h>
// 下头文件包含网际套接字变量的类型定义等。
#include <netinet/in.h>
// 下头文件包含bzero()函数等
#include <string.h>
// 下头文件包含errno变量等
#include <errno.h>
// 下头文件包含一些时间函数
#include <time.h>

#define MAXLINE 100
#define LISTENQ 5

int main(int argc, char **argv)
{
// 定义监听套接字描述符listenfd
// 定义连接套接字描述符
int listenfd, connfd;
// 定义套接字变量servaddr( 注意这里存放的是客户端的信息 )
struct sockaddr_in servaddr;
// 定义字符数组buff暂存时间
char buff[MAXLINE];

// 定义时间相关变量
time_t ticks;
struct tm *ptm;

// 创建一个网际字节流套接字
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
puts("创建网际套接字失败\n");
return 1;
}

// 将套接字变量servaddr清零
bzero(&servaddr, sizeof(servaddr));
// 给套接字变量的协议段赋值( AF_INET表示IPv4协议 )
servaddr.sin_family = AF_INET;
// 给套接字变量的端口段赋值( 13是时间服务器端口 )
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
// 给套接字变量的IP段赋值( argv[1]存放服务器IP )
servaddr.sin_port = htons(13);

// 把指定的协议地址绑定到套接字
if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 ) {
puts("绑定服务端口失败\n");
return 2;
}
// 将套接字转换为监听套接字类型
if (listen(listenfd, LISTENQ) < 0) {
puts("创建监听套接字失败\n");
return 3;
}

while (1) {
// 等待客户呼叫,若收到呼叫则返回一个已连接套接字。
connfd = accept(listenfd, (struct sockaddr *)NULL, NULL);

/*
* 获取时间并存放进buff数组
*/
ticks = time(NULL);
ptm = localtime(&ticks);
snprintf(buff, sizeof(buff), "现在是北京时间:\n%d年 %d月 %d日 %d时 %d分", ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min);

// 往客户端缓冲区中写入时间
while (write(connfd, buff, strlen(buff)) < 0) {
puts("写入数据失败\n");
return  4;
}
// 关闭连接
if (close(connfd)) {
puts("关闭套接字失败\n");
return 5;
}
}
}


运行测试

  1. 在一个终端用超级用户权限启动服务器:

  


  2. 在另一个终端中启动客户端并输进本机IP或者127.0.0.1:

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: