【ARM&Linux】UDP网络编程模型

《UDP网络编程模型示例》



1、模型函数化

  • 【服务器】:

    1. 创建socket
    2. 绑定地址
    3. 收发数据
    4. 结束连接
  • 【客户端】:

    1. 创建socket
    2. 收发数据
    3. 结束连接

2、示例代码

/****************************************************************************************
* 文件名: service.c
* 创建者: 
* 时 间: 
* 联 系: 
* 简 介: UDP程序设计模型,函数API参考文档《Unix环境高级编程》
*****************************************************************************************/

/***********************************************************
函数学习及流程:
    1、创建socket: 
    2、绑定地址:
    3、接收数据:ssize_t recvfrom(int socket,
                                void *restrict buffer,
                                size_t length,
                                int flags, 
                                struct sockaddr *restrict address,
                                socklen_t *restrict address_len);
        参数一:指明哪个socket
        参数二:用于存放收到的数据
        参数三:接收多少字节
        参数四:标志,一般为0
        参数五:接收数据的目标地址
        参数六:接收数据的目标地址的长度
        返回值:成功返回接收到的字节书,失败-1

    4、发送数据:ssize_t sendto(int socket, 
                            const void *message, 
                            size_t length,
                            int flags, 
                            const struct sockaddr *dest_addr,
                            socklen_t dest_len);
        参数一:指明是哪个socket
        参数二:要发送的数据
        参数三:要发送的数据长度
        参数四:标志,一般为0
        参数五:目标地址
        参数六:目标地址长度
        返回值:成功返回发送成功的字节数,失败-1

    5、关闭套接字

本例程只详细介绍了发送和接收函数,其他函数详细信息见另一篇tcp编程的博客:http://blog.csdn.net/qq153471503/article/details/79329089


【综合实例】:
    服务器一直接收数据并打印,直到收到end结束接收,然后发送向客户端发送通知数据。
    客户端一直获取键盘输入并发送数据,并显示发送结果,键入end结束发送,并接收服务器的通知数据并打印。

************************************************************/
#include "mytype.h"

int main()
{
    int fd;
    char buf[64];
    socklen_t addr_length = sizeof(struct sockaddr_in);
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;

    // 1、创建socket
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(fd == -1)
    {
        DEBUG_ERROR("service creat socket failed. \n");
        exit(EXIT_FAILURE);
    }

    // 2、绑定地址
    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(8080);
    server_addr.sin_family = AF_INET;
    bind(fd, &server_addr, sizeof(server_addr));

    // 3、接收数据
    bzero(&client_addr, sizeof(client_addr));
    client_addr.sin_addr.s_addr = inet_addr("192.168.0.252");
    client_addr.sin_port = htons(8080);
    client_addr.sin_family = AF_INET;

    while(1)
    {
        if( recvfrom(fd, buf, sizeof(buf), 0, &client_addr, &addr_length) > 0)
        {
            if(strncmp(buf, "end", 3) == 0)
            {
                break;
            }
            DEBUG_INFO("receive data from [%s] : %s \n", inet_ntoa(client_addr.sin_addr), buf);
        }
    }

    bzero(buf, sizeof(buf));
    strcpy(buf, "server stop. \n");
    if( sendto(fd, buf, strlen(buf), 0, &client_addr, sizeof(client_addr)) <= 0 )
    {
        DEBUG_WARNING("server send to client failed. \n");
    }else{
        DEBUG_INFO("server send result successful. \n");
    }

    // 5、关闭
    close(fd);
    return 0;
}

#include "mytype.h"

/***********************************************************
函数学习及流程:
    1、创建
    2、发送
    3、接收
    4、结束连接
************************************************************/
int main()
{
    int fd;
    char buf[64];
    socklen_t addr_length = sizeof(struct sockaddr_in);
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;

    // 1、创建socket
    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(fd == -1)
    {
        DEBUG_ERROR("service creat socket failed. \n");
        exit(EXIT_FAILURE);
    }

    // 2、循环发送数据
    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_addr.s_addr = inet_addr("192.168.0.252");
    server_addr.sin_port = htons(8080);
    server_addr.sin_family = AF_INET;
    while(1)
    {
        DEBUG_PRINTF("Please input : ");
        fgets(buf, sizeof(buf), stdin);

        if( sendto(fd, buf, strlen(buf), 0, &server_addr, sizeof(server_addr)) > 0 )
        {
            DEBUG_INFO("client send successful. \n");
        }

        if(strncmp(buf, "end", 3) == 0 )
        {
            break;
        }
    }

    // 3、接收通知数据
    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(8080);
    server_addr.sin_family = AF_INET;
//  memset(buf, 0, sizeof(buf));
    if(recvfrom(fd, buf, sizeof(buf), 0, &server_addr, &addr_length) > 0)
    {
        DEBUG_INFO("receive server data is : %s \n", buf);
    }
    // 4、结束连接
    close(fd);

    return 0;
}


3、运行结果

  • 【Makefile】
    这里写图片描述
     
  • 【运行结果】
    这里写图片描述

4、mytype.h

/****************************************************************************************
* 文件名: mytype.h
* 创建者: Kun
* 联 系: [email protected]
* 简 介: linux常用类型定义
* 最后修改时间: 2018/2/15 17:57
*****************************************************************************************/

#ifndef _MYTYPE_H_
#define _MYTYPE_H_

//--------------------------< 预添加头文件包含 >----------------------//

#define USE_TIME 0
#define USE_SIGNAL 0
#define USE_SHARE_MEMORY 0
#define USE_SEMAPHORE_NAME 0
#define USE_SEMAPHORE_UNNAMED 0
#define USE_MSG_QUEUE 0
#define USE_FILE_CTL 0
#define USE_THREAD 0
#define USE_SOCKET 1
//-------------------------------< end ----------------------------//


//---------------------------< includes >---------------------------//
// c标准库头文件
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

// 信号使用相关头文件
#if USE_SIGNAL
#include <sys/signal.h>
#endif // USE_SIGNAL

// 有名信号量操作相关头文件
#if USE_SEMAPHORE
#include <sys/sem.h>
#include <sys/ipc.h>
#endif // USE_SEMAPHORE

// 无名信号量操作相关头文件
#if USE_SEMAPHORE_UNNAMED
    #include <semaphore.h>
#endif // USE_SEMAPHORE_UNNAMED

// 共享内存操作相关头文件
#if USE_SHARE_MEMORY
#include <sys/shm.h>
#endif // USE_SHARE_MEMORY

// 消息队列相关头文件
#if USE_MSG_QUEUE
    #if !USE_SEMAPHORE
        #include <sys/ipc.h>
    #endif
#include <sys/msg.h>
#endif // USE_MSG_QUEUE

// 系统调用式文件编程头文件
#include <fcntl.h>

// 该文件所定义的接口通常都是大量针对系统调用的封装,
// 如 fork、pipe 以及各种 I/O 原语(read、write、close 等等)。
#include <unistd.h>

// linux系统中类型定义相关头文件
#include <sys/types.h>

// 文件状态,是unix/linux系统定义文件状态所在的伪标准头文件。
#if USE_FILE_CTL
#include <sys/stat.h>
#endif // USE_FILE_CTL

// 时间编程相关头文件
#if USE_TIME
#include <sys/time.h>
#endif // USE_TIME


// 线程相关头文件
#if USE_THREAD
    #include <pthread.h>
#endif // USE_THREAD

// 网络编程相关头文件
#if USE_SOCKET
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
#endif // USE_SEMAPHORE_NAME
//-------------------------< includes end >-------------------------//


// bool类型定义
#ifndef bool
typedef unsigned int bool;
#endif
enum
{
    true = 1,
    false = !true
};

// 常用无符号数据类型定义
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned short ushort;

//----------------------< 调试信息输入相关宏定义 >----------------------//
#define DEBUG_INFO(...) printf("Info: "); printf(__VA_ARGS__)
#define DEBUG_ERROR(...) printf("Error: "); printf(__VA_ARGS__)
#define DEBUG_WARNING(...) printf("Warning: "); printf(__VA_ARGS__)
#define DEBUG_PRINTF(...) printf(__VA_ARGS__)
//------------------------------------------------------------------//

// 有名信号量使用封装结构
#if USE_SEMAPHORE
typedef struct sem_use SEM_USE;
struct sem_use
{
    int semid;
    key_t key;
    struct sembuf sops;
};
#endif // USE_SEMAPHORE

// 共享内存使用封装结构
#if USE_SHARE_MEMORY
typedef struct shmem_use SHMEM_USE;
struct shmem_use
{
    int shmid;
    key_t key;
};

#define BUF_SIZE 1024*1 //共享内存大小
typedef struct shmem_area SHMEM_AREA;
struct shmem_area
{
    bool isnull;
    char data[BUF_SIZE];
};

#endif // USE_SHARE_MEMORY

// 消息队列使用封装结构
#if USE_MSG_QUEUE
typedef struct msg_queue_use MSG_QUEUE_USE;
struct msg_queue_use{
    key_t key;
    int msgid;
};
#endif // USE_MSG_QUEUE

#if USE_SOCKET
//tcp客户端使用封装结构
typedef struct use_tcp_client{
    int fd;
    struct sockaddr_in server_addr;
    socklen_t addr_length;
}USE_TCP_CLIENT;
//tcp服务端使用结构封装
typedef struct use_tcp_service{
    int fd;
    int newfd;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    socklen_t addr_length;
}USE_TCP_SERVICE;

#endif // USE_SOCKET


#endif // _TYPE_H_




ends

猜你喜欢

转载自blog.csdn.net/qq153471503/article/details/79329466