基于UDP的简单通信例程

相关代码:

//客户端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <unistd.h>

using namespace std;

const int MAX_LEN = 4096;                //缓存区长度
const char serverip[] = "192.168.124.2"; //设置服务器地址 此处为本机地址
const int servercom = 8080;              //设置服务器监听端口
const int localcom = 8081;               //设置本机端口

int main()
{
    int fd;                                    //通信描述符
    int count;                                 //接收字节数
    char recvbuff[MAX_LEN], sendbuff[MAX_LEN]; //定义接收缓存区和发送缓存区
    struct sockaddr_in localaddr;
    struct sockaddr_in serveraddr;

    socklen_t locallen = sizeof(localaddr);
    socklen_t serverlen = sizeof(serveraddr);

    //建立UDP的通信文件描述符
    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        cout << "creat fd error" << endl;
        return -1;
    }

    //填写服务器地址信息
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(servercom); //此处转换为网络字节序
    //填入服务器的IP并转换为网络字节序
    if (inet_pton(AF_INET, serverip, &serveraddr.sin_addr) <= 0)
    {
        cout << "transf  serverip error!" << endl;
        return -1;
    }

    //设定本客户端的地址信息
    memset(&localaddr, 0, sizeof(localaddr));
    localaddr.sin_family = AF_INET;
    localaddr.sin_port = htons(localcom);          //此处转换为网络字节序
    localaddr.sin_addr.s_addr = htonl(INADDR_ANY); //设置本地IP

    //绑定通信描述符和本地地址端口
    if ((bind(fd, (struct sockaddr *)&localaddr, locallen)) < 0)
    {
        cout << "bind fail" << endl;
        return -1;
    }

    cout << "client init successed" << endl;
    cout << "port:" << ntohs(localaddr.sin_port)
         << "  ip:" << inet_ntoa(localaddr.sin_addr) << endl;

    while (1)
    {
        cout << "input:" << endl;
        memset(sendbuff, 0, sizeof(sendbuff)); //清零
        cin.getline(sendbuff, MAX_LEN);        //等待写入
        //向服务器发送数据 从localaddr发到serveraddr
        if (sendto(fd, sendbuff, sizeof(sendbuff), 0, (struct sockaddr *)&serveraddr, serverlen) < 0)
        {
            cout << "send fail!" << endl;
            return -1;
        }
        //从服务器接受消息
        count = recvfrom(fd, recvbuff, sizeof(recvbuff), 0, (struct sockaddr *)&serveraddr, &serverlen);
        if (count == -1)
        {
            cout << "receive fail" << endl;
            return -1;
        }
        else
            cout << "receive message: " << recvbuff << endl; //显示接收的字符
        cout << "clien port:" << ntohs(localaddr.sin_port)
             << "  ip:" << inet_ntoa(localaddr.sin_addr) << endl;
        cout << "server port:" << ntohs(serveraddr.sin_port)
             << "  ip:" << inet_ntoa(serveraddr.sin_addr) << endl;
    }
    close(fd);
    return 0;
}
//服务器端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <iostream>

using namespace std;

const int MAX_LEN = 4096;   //缓存区长度
const int servercom = 8080; //服务器端口

int main()
{
    int listenfd;
    struct sockaddr_in servaddr; //服务器监听信息
    struct sockaddr_in clieaddr; //获取客户端地址信息
    socklen_t serverlen = sizeof(servaddr);
    socklen_t clienlen = sizeof(clieaddr);

    char buff[MAX_LEN];
    int recv_count = 0;

    //建立监听文件描述符
    if ((listenfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    {
        cout << "creat fd error!" << endl;
        return -1;
    }

    //填入服务器通信地址信息
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //地址为任意本机地址
    servaddr.sin_port = htons(servercom);

    //将地址信息与描述符绑定
    if (bind(listenfd, (struct sockaddr *)&servaddr, serverlen) < 0)
    {
        cout << "bind error!" << endl;
        return -1;
    }

    //必要信息输出
    cout << "server init successed!" << endl;
    cout << "port:" << ntohs(servaddr.sin_port)
         << "  ip:" << inet_ntoa(servaddr.sin_addr) << endl;
    cout << "wait for connect!" << endl;
    while (1)
    {
        //等待从clieaddr地址接收数据,监听数据端口为servaddr,同时把客户端信息放在clieaddr中
        recv_count = recvfrom(listenfd, buff, MAX_LEN, 0, (struct sockaddr *)&clieaddr, &clienlen);
        if (recv_count == -1)
        {
            cout << "receive data error!" << endl;
            return -1;
        }
        buff[recv_count] = '\0';                          //在收到的数据后添加结束符号
        cout << "recv msg from client: " << buff << endl; //输出接收的字符
        //将原数据发给客户端clieaddr
        sendto(listenfd, buff, sizeof(buff), 0, (struct sockaddr *)&clieaddr, clienlen);
        //显示客户端的地址和服务端的地址
        cout << "clien port:" << ntohs(clieaddr.sin_port)
             << "  ip:" << inet_ntoa(clieaddr.sin_addr) << endl;
        cout << "server port:" << ntohs(servaddr.sin_port)
             << "  ip:" << inet_ntoa(servaddr.sin_addr) << endl;
    }
    close(listenfd);
    return 0;
}

心得:

客户端
1.声明客户端地址、服务器地址
2.建立文件描述符fd
3.填写服务器信息,IP、端口等
4.填写本地信息,主要是端口,并与fd绑定bind(可选,选择后客户端不会再自动选择端口)
5.输入信息,sendto服务器地址信息
6.recvfrom服务器地址信息

服务端
1.声明客户端地址、服务器地址
2.建立文件描述符fd
3.填写服务器信息,IP、端口等
4.将服务器信息与fd绑定bind
5.recvfrom监听服务器端口信息,将得到的数据存入buff,将客户端信息存入客户端地址信息
6.sendto客户端地址将信息发送回客户端

***注意***
如果期望打印相关的地址ip\端口信息需要将其从网络字节序转回主机字节序

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值