Linux的UDP基础编程

UDP通信机制

相比较于TCP通信,UDP通信是面向无连接的通信,所以没有TCP中的监听和连接等涉及面向连接的过程,UDP的主要通信过程如下图所示:

相比较TCP通信,UDP相对而言比较简单,虽然UDP是无连接的通信,但是依然有服务器和客户端之分,且通信的时候直接指定对方地址即可,无视对方是否能收到你发送的消息。且UDP通信不再使用read/write发送消息和读取消息了,因为没有连接,所以需要指定地址,而read和write没有能够提供地址的功能,所以需要使用其他方法替代。这里使用了sendto/recvfrom来保证双方能够通信,这两个函数的具体情况如下所示:

ssize_t sendto(int socket, const void *message, size_t length,int flags, const struct sockaddr *dest_addr,socklen_t dest_len);
/**
 *  sendto可以用来发送面向连接(TCP)和非连接(UDP)的消息。当无连接时,需要提供地址信息,而有连接时会忽略提供的地址信息。
 *  头文件      : #include <sys/socket.h>
 *  socket      : 通信套接字
 *  message     : 消息内容
 *  length      : 消息长度
 *  flags       : 指定传输的消息类型,默认使用0即可。
 *  dest_addr   : 消息目的地地址
 *  dest_len    : 地址长度
 */

ssize_t recvfrom(int socket, void *buffer, size_t length, int flags, struct sockaddr *address, socklen_t *address_len);
/**
 *  sendto可以用来接收面向连接(TCP)和非连接(UDP)的消息。当无连接时,需要提供地址信息,而有连接时会忽略提供的地址信息。
 *  头文件      : #include <sys/socket.h>
 *  socket      : 通信套接字
 *  buffer      : 消息内容
 *  length      : 消息长度
 *  flags       : 指定传输的消息类型,默认使用0即可。
 *  address     : 消息目的地地址
 *  address_len : 地址长度
 */

UDP通信示例

UDP服务器

//
//  UDP服务器
//  SingletonDemo
//
//  Created by arbboter on 15/1/16.
//  Copyright (c) 2015年 arbboter. All rights reserved.
//
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        printf("Usage: %s port\n", argv[0]);
        exit(1);
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(argv[1]));
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    int sock = -1;
    // 指定SOCK_DGRAM表示UDP
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if( sock < 0)
    {
        perror("创建socket失败!\n");
        return -1;
    }

    if( bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("bind失败!\n");
        exit(1);
    }

    char buff[512] = {0};
    struct sockaddr_in clientAddr;
    socklen_t len = sizeof(clientAddr);
    ssize_t nCount = 0;
    while(true)
    {
        printf("waitting for connected...\n");
        // 阻塞直到收到客户端的的连接发送过来的数据
        nCount = recvfrom(sock, buff, sizeof(buff), 0, (struct sockaddr*)&clientAddr, &len);
        if (nCount > 0)
        {
            // 收到消息同时把收到的再发回去
            buff[nCount] = '\0';
            printf("[%s:%u] -> %s\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port), buff);
            sendto(sock, buff, nCount, 0, (struct sockaddr *)&clientAddr, sizeof(clientAddr));
        }
        else
        {
            perror("recvfrom错误!\n");
            break;
        }
    }
    return 0;
}

UDP客户端

//
//  UDP客户端
//  SingletonDemo
//
//  Created by arbboter on 15/1/16.
//  Copyright (c) 2015年 arbboter. All rights reserved.
//
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(int argc, char **argv)
{
    if (argc != 3)
    {
        printf("Usage: %s ip port", argv[0]);
        return -1;
    }

    struct sockaddr_in addr;
    int sock = -1;

    // 创建UDP类型的socket
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if ( sock <0)
    {
        perror("创建socket失败!\n");
        return -1;
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(argv[2]));
    addr.sin_addr.s_addr = inet_addr(argv[1]);
    if (addr.sin_addr.s_addr == INADDR_NONE)
    {
        printf("服务器IP地址有误!请重试...\n");
        close(sock);
        return -1;
    }

    char buff[512] = {0};
    socklen_t len = sizeof(addr);
    ssize_t nCount = 0;
    while (1)
    {
        printf("请输入要发送的消息:");
        scanf("%s", buff);

        // 直接往给定的地址发送数据,不管对方是否能够接收
        sendto(sock, buff, strlen(buff), 0, (struct sockaddr *)&addr, sizeof(addr));

        len = sizeof(addr);
        // 等待服务器返回信息直到收到数据
        nCount = recvfrom(sock, buff, sizeof(buff), 0, (struct sockaddr *)&addr, &len);
        if( nCount > 0 )
        {
            buff[nCount] = '\0';
            printf("server -> %s\n", buff);
        }
        else if( nCount == 0 )
        {
            printf("服务器已关闭!\n");
            close(sock);
            break;
        }
        else
        {
            perror("接收消息失败!\n");
            close(sock);
            break;
        }
    }

    return 0;
}
时间: 2024-08-25 16:42:47

Linux的UDP基础编程的相关文章

Linux下C基础编程----写在Blog之前的话

找个2个星期的实习吧.各种坎坷.既然公司只是做广告.为毛让我去笔试!严重鄙视.想在也想开了,争取过了,结果顺其自然吧.还是好好写自己的学习心得吧,希望和我以前一样迷茫的各位同学,少走一点弯路.好了,切入正题: 一.参考书籍: 好的书籍的作用不用多说了.先得有基础,推荐以下基本书吧,个人觉得不错. <C和指针> <C专家编程> <C陷阱与缺陷> 上面三本书,认真看吧,特别是C和指针,可以当教材看,认真做做书后习题,我从这本书中受益菲浅 ,后两本用于提高,比如可以知道: c

大数据学习初体验:Linux学习+Shell基础编程+hadoop集群部署

距离上次博客时间已经9天,简单记录下这几天的学习过程 2020-02-15 10:38:47 一.Linux学习 关于Linux命令,我在之前就已经学过一部分了,所以这段时间的linux学习更多的是去学习Linux系统的安装以及相关配置多一些,命令会一些比较常用的就够了,下面记录下安装配置Linux系统时的注意事项. 这里配置的虚拟机的内存为4g 使用的 CentOS-6.5-x86_64-minimal.iso 映射文件 在进入linux系统中时,需要将虚拟机的主机名修改成自己想要的名字,还要

Linux的TCP基础编程

网络地址数据结构问题 首先,先来说网络中的编程地址,不知有没有人发现在我们网络编程中不仅仅只有一个地址数据结构,而且很多时候我们在调用网络接口的时候还要强制转换参数的类型.对,我说的就是数据结构sockaddr和sockaddr_in这两货,而如果你足够仔细的话,你会发现,编程中我们使用的大部分是sockaddr_in,但是我们调用的网络接口却几乎都是(不知道有没有不是的啊,我木有去调查)sockaddr类型的,为什么?下面先来看看这两种数据结构的定义,如下所示: /** * 通用网络地址结构

Linux之V4L2基础编程【转】

转自:http://www.cnblogs.com/emouse/archive/2013/03/04/2943243.html 本文内容来源于网络,本博客进行整理. 1. 定义 V4L2(Video For Linux Two) 是内核提供给应用程序访问音.视频驱动的统一接口. 2. 工作流程: 打开设备-> 检查和设置设备属性-> 设置帧格式-> 设置一种输入输出方法(缓冲 区管理)-> 循环获取数据-> 关闭设备. 3. 设备的打开和关闭: #include <f

TCP/UDP网络编程的基础知识与基本示例(windows和Linux)

一.TCP编程的一般步骤 服务器端: 1.创建一个socket,用函数socket() 2.绑定IP地址.端口等信息到socket上,用函数bind() 3.开启监听,用函数listen() 4.接收客户端上来的连接,用函数accept() 5.收发数据,用函数send()和recv(),或者read()和write() 6.关闭网络连接 7.关闭监听 客户端: 1.创建一个socket,用函数socket() 2.设置要连接的对方IP地址和端口等属性 3.连接服务器,用函数connect()

[Z] linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO

原文链接:http://blog.csdn.net/colzer/article/details/8169075 IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file descriptor(fd,文件描述符).而对一个socket的读写也会有相应的描述符,称为socketfd(socket描述符).描述符就是一个数字,指向内核中一个结构体(文件路径,数据

Linux应用程序设计之网络基础编程

1.TCP/IP协议概述 1.1.OSI参考模型及TCP/IP参考模型 OSI协议参考模型是基于国际标准化组织(ISO)的建议发展起来的,从上到下工分为7层:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层.与此相区别的TCP/IP协议模型一开始就遵循简单明确的设计思路,它将OSI的7层参考模型简化为4层,从而得到有利于实现和使用.TCP/IP协议参考模型和OSI协议参考模型的对应关系如下图所示: 网络接口层:负责将二进制流转换为数据帧,并进行数据帧的发送和接收.要注意的是数据帧是独立

linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)

IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file descriptor(fd,文件描述符).而对一个socket的读写也会有相应的描述符,称为socketfd(socket描述符).描述符就是一个数字,指向内核中一个结构体(文件路径,数据区,等一些属性).那么我们的应用程序对文件的读写就通过对描述符的读写完成. linux将内存分为内核区,用户区.l

LINUX下C语言编程基础

实验二 Linux下C语言编程基础 一.实验目的 1. 熟悉Linux系统下的开发环境 2. 熟悉vi的基本操作 3. 熟悉gcc编译器的基本原理 4. 熟练使用gcc编译器的常用选项 5 .熟练使用gdb调试技术 6. 熟悉makefile基本原理及语法规范 7. 掌握静态库和动态库的生成 二.实验步骤 1. 快捷键 Ubuntu中: 2. vim VIM是一个非常好的文本编辑器,很多专业程序员使用VIM编辑代码,即使以后你不编写程序,只要跟文本打交道,都应该学学VIM,可以浏览参考一下普通人