Linux C语言 32-网络编程之UDP例程

news/2024/5/18 16:09:07 标签: 网络, linux, c语言, 开发语言, udp, 服务端, 客户端

Linux C语言 32-网络编程之UDP例程

本节关键字:C语言 网络编程 UDP协议 套接字操作 服务端 客户端
相关C库函数:setsockopt, socket, bind, recvfrom, sendto, close

相关接口介绍

Linux C语言 30-套接字操作

例程执行任务说明

本例程中服务端的任务:

本例程中客户端的任务:

UDP协议服务端例程实现

// udpserver.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>


void msleep(int msecs);
int  getOneServerSocket(const char *ip, int port);


int main(int argc, char *argv[])
{
    int rc, rxn, txn, srvfd, port;
    int addrLen;
    struct sockaddr_in remoteAddr;
    
    char ip[32] = {0};
    char rxBuffer[1024] = {0};
    char txBuffer[1024] = {0};
    
    if (argc != 3)
    {
        printf("please input correct arguments:\n");
        printf("\tudpserver ip port\n\n");
        return -1;
    }
    
    // 解析ip和port
    strcpy(ip, argv[1]);
    port = atoi(argv[2]);
    printf("ip: %s, port: %d\n", ip, port);
    
    // 创建套接字
    srvfd = getOneServerSocket(ip, port);
    
    addrLen = sizeof(remoteAddr);
    while (1)
    {
        bzero(rxBuffer, sizeof(rxBuffer));
        rxn = recvfrom(srvfd, rxBuffer, sizeof(rxBuffer)-1, 0, (struct sockaddr*)&remoteAddr, &addrLen);
        if (rxn > 0)
        {
            printf("client[%s:%d] socket:%d  %s\n", inet_ntoa(remoteAddr.sin_addr), ntohs(remoteAddr.sin_port), srvfd, rxBuffer);
            
            bzero(txBuffer, sizeof(txBuffer));
            sprintf(txBuffer, "server reply client[%s:%d] -> %s", inet_ntoa(remoteAddr.sin_addr), ntohs(remoteAddr.sin_port), rxBuffer);
            sendto(srvfd, txBuffer, strlen(txBuffer), 0, (struct sockaddr*)&remoteAddr, addrLen);
        }
    }
    
    close(srvfd);
    
    return 0;
}

void msleep(int msecs)
{
    struct timeval stoptime;
    stoptime.tv_sec  = (int)(msecs/1000);
    stoptime.tv_usec = (int)(msecs%1000)*1000;
    select(0, 0, 0, 0, &stoptime);
}

int getOneServerSocket(const char *ip, int port)
{
    int rc, srvfd, reused, timeout;
    struct sockaddr_in addr;
    
    srvfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (srvfd == -1)
    {
        perror("create socket");
        exit(-1);
    }
    
    // 设置端口复用
    reused = 1;
    rc = setsockopt(srvfd, SOL_SOCKET, SO_REUSEADDR, &reused, sizeof(reused));
    if (rc == -1)
    {
        perror("SO_REUSEDADDR");
        goto EXIT;
    }
    // 设置发送超时限制
    timeout = 1000; // 1秒
    setsockopt(srvfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
    if (rc == -1)
    {
        perror("SO_SNDTIMEO");
        goto EXIT;
    }
    
    // 套接字绑定本地的ip和port
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr(ip);
    bzero(addr.sin_zero, sizeof(addr.sin_zero));
    
    rc = bind(srvfd, (struct sockaddr*)&addr, sizeof(addr));
    if (rc == -1)
    {
        perror("bind");
        goto EXIT;
    }
    
    return srvfd;
    
EXIT:
    close(srvfd);
    exit(-1);
}

UDP协议客户端例程实现

// udpclient.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>


void msleep(int msecs);
int  getOneClientSocket(const char *ip, int port, struct sockaddr_in *addr);

int main(int argc, char *argv[])
{
    int rc, rxn, txn, clifd, port;
    int addrLen;
    struct sockaddr_in serverAddr;
    struct sockaddr_in remoteAddr;
    
    unsigned int packet_id = 0;
    char ip[32] = {0};
    char rxBuffer[1024] = {0};
    char txBuffer[1024] = {0};
        
    if (argc != 3)
    {
        printf("please input correct arguments:\n");
        printf("\tudpserver ip port\n\n");
        return -1;
    }
    
    // 解析ip和port
    strcpy(ip, argv[1]);
    port = atoi(argv[2]);
    printf("ip: %s, port: %d\n", ip, port);
    
    // 创建套接字
    clifd = getOneClientSocket(ip, port, &serverAddr);
    
    addrLen = sizeof(remoteAddr);
    while (1)
    {
        bzero(txBuffer, sizeof(txBuffer));
        sprintf(txBuffer, "Hello, i'm client[%d], packet id: %d", clifd, packet_id++);
        sendto(clifd, txBuffer, strlen(txBuffer), 0, (struct sockaddr*)&serverAddr, addrLen);
        
        bzero(rxBuffer, sizeof(rxBuffer));
        rxn = recvfrom(clifd, rxBuffer, sizeof(rxBuffer)-1, 0, (struct sockaddr*)&remoteAddr, &addrLen);
        if (rxn > 0)
        {
            printf("server[%s:%d] -> %s\n", inet_ntoa(remoteAddr.sin_addr), ntohs(remoteAddr.sin_port), rxBuffer);
        }
        
        msleep(1000);
    }
    
    return 0;
}

void msleep(int msecs)
{
    struct timeval stoptime;
    stoptime.tv_sec  = (int)(msecs/1000);
    stoptime.tv_usec = (int)(msecs%1000)*1000;
    select(0, 0, 0, 0, &stoptime);
}

int getOneClientSocket(const char *ip, int port, struct sockaddr_in *addr)
{
    int rc, srvfd, reused, timeout;
    
    srvfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (srvfd == -1)
    {
        perror("create socket");
        exit(-1);
    }
    
    // 设置端口复用
    reused = 1;
    rc = setsockopt(srvfd, SOL_SOCKET, SO_REUSEADDR, &reused, sizeof(reused));
    if (rc == -1)
    {
        perror("SO_REUSEDADDR");
        goto EXIT;
    }
    // 设置发送超时限制
    timeout = 1000; // 1秒
    setsockopt(srvfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
    if (rc == -1)
    {
        perror("SO_SNDTIMEO");
        goto EXIT;
    }
    
    // 套接字绑定本地的ip和port
    addr->sin_family = AF_INET;
    addr->sin_port = htons(port);
    addr->sin_addr.s_addr = inet_addr(ip);
    bzero(addr->sin_zero, sizeof(addr->sin_zero));
    
    return srvfd;
    
EXIT:
    close(srvfd);
    exit(-1);
}

例程编译及运行

UDP服务端例程编译及运行结果
$ gcc udpserver.c -o udpserver
$ ./udpserver 0.0.0.0 88888
ip: 0.0.0.0, port: 88888
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 0
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 1
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 2
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 3
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 4
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 5
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 6
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 7
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 8
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 9
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 10
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 11
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 12
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 13
client[192.168.146.128:52147] socket:3  Hello, i'm client[3], packet id: 14
UDP客户端例程编译及运行结果
# 服务端IP为192.168.146.128
$ gcc udpclient.c -o udpclient
$ ./udpclient 192.168.146.128 88888
ip: 192.168.146.128, port: 88888
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 0
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 1
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 2
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 3
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 4
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 5
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 6
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 7
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 8
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 9
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 10
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 11
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 12
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 13
server[192.168.146.128:23352] -> server reply client[192.168.146.128:52147] -> Hello, i'm client[3], packet id: 14

http://www.niftyadmin.cn/n/5223295.html

相关文章

C语言 移位操作符

<< 左移操作符>> 右移操作符 注&#xff1a;移位操作符的操作数只能是整数。 移位操作符移动的是二进制位。 整数的二进制表示有3种&#xff1a; 原码反码补码 正的整数的原码、反码、补码相同。 负的整数的原码、反码、补码是要计算的。 由负整数原码计算出反…

用C++和python混合编写数据采集程序?

之前看过一篇文章&#xff0c;主要阐述的就是多种语言混合编写爬虫程序&#xff0c;结合各种语言自身优势写一个爬虫代码是否行得通&#xff1f;觉得挺有意思的&#xff0c;带着这样的问题&#xff0c;我尝试着利用我毕生所学写了一段C和python混合爬虫程序&#xff0c;目前运行…

【前端】js 多个并行的Promise阻塞工具 指定同时执行数量

“多线程”Promise 工具类 vue that this 或者用 全局变量 map {count:0} //阻塞并获取额度 await WTool.Thread.sleepLimit(that, 变量名称, 500) await WTool.Thread.sleepLimit(map, count, 500) Thread:{/*** 阻塞x毫秒* 使用方法* await sleep&#xff08;5000&…

Filament引擎分析--command抽象设备API

1. 前言 Filament中使用了FrameGraph来管理渲染管线&#xff0c;需要准备两点&#xff1a; 设备接口抽象&#xff1a;设备API抽象为Command资源抽象&#xff1a;使用虚拟资源&#xff0c;在实际用到时再创建&#xff0c;方便剔除无用资源 下面就围绕Filament中设备API抽象为…

UniApp项目中 使用微信小程序原生语言 进行开发

看效果 wxcomponents 下放的是微信小程序原生代码写的组件。我进行了封装 上干货 在你下uniApp 项目的根目录创建一个 wxcomponents 名字千万不要错 京东、支付宝灯参考下面图片 官方文档也有介绍 然后在你需要引入原生功能的页面里面引入你的组件&#xff08;我这里提前已经放…

基于Python+OpenCV+dlib+Tensorflow深度学习的人脸表情识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 人脸表情识别是一种重要的计算机视觉任务&#xff0c;它涉及到对人脸图像中的表情进行分类和理解。在这个系统中&am…

排序算法:n个0~1000之间的整数,将他们从大到小排序

上榜理由&#xff1a; 如果没见过这种排序题&#xff0c;可能首先想到的就是常用的排序算法&#xff0c;比如快速排序&#xff0c;归并排序&#xff0c;那如果输入的n足够大&#xff0c;时间复杂度肯定比较高。其实题目0-1000的范围是一个题眼&#xff0c;所以一定有更优的排序…

QT配合CSS隐藏按钮

第一种方法 在Qt的CSS样式表中&#xff0c;使用 visibility 属性来隐藏按钮。设置 visibility 为 hidden 不可见&#xff0c;而设置为 visible 则可见。 隐藏所有 QPushButton QPushButton {visibility: hidden; }隐藏特定的按钮&#xff0c;用按钮的名称或样式类进行定位就…