例、编写一个从气象站获取天气信息的程序。气象站发送数据到服务器,服务器存储气象站发来的天气信息,客户端向服务器发出请求,获取天气信息;服务器就将天气信息发送给客户端。
思路:
气象站、服务器、客户端三者各有一个程序,气象站程序主要就向服务器发送天气信息。天气信息用一个结构体封装起来,结构体成员主要有消息类型(用于服务器区分是气象站的消息还是客户端的消息)、温度、湿度等天气状况,在这里只是模拟三者之间的网络通信。服务器用于接收气象站和客户端的消息,如果是气象站发来的消息那肯定是天气信息,服务器就存储起来;如果是客户端发来的消息,那肯定是请求获取天气信息,服务器就把从气象站获取的天气信息(之前存储好的)发给客户端。客户端程序发送请求和接收天气信息。
头文件com.h
#ifndef UDP_STRUCT_TEST_H
#define UDP_STRUCT_TEST_H
#define PORT 5549
struct mesdata
{
int type;//定义消息类型,用于区分服务器、气象站和客户端的消息
int temp;//温度
int hum;//湿度
}__attribute__((packed));
#endif
气象站程序:cast.c
/*气象站程序,用于向服务器发送气象信息*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <string.h>
#include "com.h"
int main(void)
{
int sock_cast;
int res;
struct mesdata data;
struct sockaddr_in cast_addr;
socklen_t castlen;
int recvsize;
sock_cast = socket(AF_INET,SOCK_DGRAM,0);
if(sock_cast < 0)
{
perror("socket()");
exit(-1);
}
cast_addr.sin_family = AF_INET;
cast_addr.sin_port = PORT;
cast_addr.sin_addr.s_addr = inet_addr("192.168.3.188");
data.type=htonl(1);
data.temp = htonl(28);
data.hum = htonl(65);
while(1)
{
res = sendto(sock_cast,&data,sizeof(data),0,\
(struct sockaddr *)&cast_addr,sizeof(cast_addr));
if(res < 0)
{
perror("sendto()");
exit(-5);
}
/*
memset(&data,0,sizeof(data));
castlen = sizeof(cast_addr);
recvsize = recvfrom(sock_cast,&data,sizeof(data),0,\
(struct sockaddr *)&cast_addr,&castlen);
if(recvsize < 0)
{
perror("recvfrom()");
close(sock_cast);
exit(-3);
}
else if(recvsize == 0)
{
printf("client be closed!\n");
close(sock_cast);
exit(0);
}
*/
sleep(1);
}
close(sock_cast);
exit(0);
}
服务器程序:server.c
/*服务器程序,用于传输存储气象信息*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <string.h>
#include "com.h"
int main(void)
{
int sock_serv;
struct sockaddr_in serv_addr;
int res;
struct mesdata recvdata;
struct sockaddr_in recv_addr;
socklen_t recvlen;
struct mesdata castdata;
struct mesdata clidata;
struct sockaddr_in cli_addr;
struct sockaddr_in cast_addr;
socklen_t clilen;
socklen_t castlen;
int recvsize;
sock_serv = socket(AF_INET,SOCK_DGRAM,0);
if(sock_serv < 0)
{
perror("socket()");
exit(-1);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = PORT;
serv_addr.sin_addr.s_addr = INADDR_ANY;
res = bind(sock_serv,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
if(res < 0)
{
perror("bind()");
exit(-2);
}
while(1)
{
memset(&recvdata,0,sizeof(recvdata));
recvlen = sizeof(recv_addr);
recvsize = recvfrom(sock_serv,&recvdata,sizeof(recvdata),0,\
(struct sockaddr *)&recv_addr,&recvlen);
if(recvsize < 0)
{
perror("recvfrom()");
close(sock_serv);
exit(-3);
}
else if(recvsize == 0)
{
printf("client be closed!\n");
close(sock_serv);
exit(0);
}
recvdata.type=ntohl(recvdata.type);
if(recvdata.type == 1)
{
castdata.temp=recvdata.temp;
castdata.hum=recvdata.hum;
}
if(recvdata.type == 2)
{
clidata.temp = castdata.temp;
clidata.hum = castdata.hum;
cli_addr = recv_addr;
res = sendto(sock_serv,&clidata,sizeof(clidata),0,\
(struct sockaddr *)&cli_addr,sizeof(cli_addr));
if(res < 0)
{
perror("sendto()");
exit(-5);
}
}
}
close(sock_serv);
exit(0);
}
客户端程序:client.c
/*手机端程序,用于向服务器获取气象信息*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <string.h>
#include "com.h"
int main(void)
{
int sock_cli;
int res;
struct mesdata data;
struct sockaddr_in cli_addr;
socklen_t clilen;
int recvsize;
sock_cli = socket(AF_INET,SOCK_DGRAM,0);
if(sock_cli < 0)
{
perror("socket()");
exit(-1);
}
cli_addr.sin_family = AF_INET;
cli_addr.sin_port = PORT;
cli_addr.sin_addr.s_addr = inet_addr("192.168.3.188");
memset(&data,0,sizeof(data));
while(1)
{
scanf("%d",&data.type);//2 获取天气信息
data.type=htonl(data.type);
res = sendto(sock_cli,&data,sizeof(data),0,\
(struct sockaddr *)&cli_addr,sizeof(cli_addr));
if(res < 0)
{
perror("sendto()");
exit(-5);
}
memset(&data,0,sizeof(data));
clilen = sizeof(cli_addr);
recvsize = recvfrom(sock_cli,&data,sizeof(data),0,\
(struct sockaddr *)&cli_addr,&clilen);
if(recvsize < 0)
{
perror("recvfrom()");
close(sock_cli);
exit(-3);
}
else if(recvsize == 0)
{
printf("client be closed!\n");
close(sock_cli);
exit(0);
}
data.temp=ntohl(data.temp);
data.hum=ntohl(data.hum);
printf("temp=%d hum=%d\n",data.temp,data.hum);
}
close(sock_cli);
exit(0);
}