基于Linux系统的一对多网络通信

本文介绍了一个使用UDP协议实现的天气信息传输系统,包括气象站、服务器和客户端三个部分。气象站负责收集并发送天气数据,服务器存储并转发数据,客户端请求并接收天气信息。

例、编写一个从气象站获取天气信息的程序。气象站发送数据到服务器,服务器存储气象站发来的天气信息,客户端向服务器发出请求,获取天气信息;服务器就将天气信息发送给客户端。

思路:

气象站、服务器、客户端三者各有一个程序,气象站程序主要就向服务器发送天气信息。天气信息用一个结构体封装起来,结构体成员主要有消息类型(用于服务器区分是气象站的消息还是客户端的消息)、温度、湿度等天气状况,在这里只是模拟三者之间的网络通信。服务器用于接收气象站和客户端的消息,如果是气象站发来的消息那肯定是天气信息,服务器就存储起来;如果是客户端发来的消息,那肯定是请求获取天气信息,服务器就把从气象站获取的天气信息(之前存储好的)发给客户端。客户端程序发送请求和接收天气信息。

头文件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);

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值