套接字---UDP用户数据报协议通讯

UDP(user Datagram Protocol)用户数据报协议

int socket (int domain, int type, int protocol);
在这里插入图片描述

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
第一个参数就是创建的套接字;第二:要绑定的IP地址和Port, 第三:地址长度
在这里插入图片描述

查找: grep -nFR 'struct sockaddr_in { ' /usr/include/
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

一、 基于UDP的本地 server 和client 通讯 代码

Makefile

Makefile

.PHONY:all
all:udpClient udpServer

udpClient:udpClient.cc
	g++ -o $@ $^ -std=c++11
udpServer:udpServer.cc
	g++ -o $@ $^

.PHONY:clean
clean:
	rm -f udpClient udpServer

Server.hpp

#pragma once

#include <iostream>
#include <string>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

class udpServer{
    private:
        std::string ip;
        int port;
        int sock;
    public:
        udpServer(std::string _ip="127.0.0.1", int _port=8080)
            :ip(_ip), port(_port)
        {

        }
        void initServer()
        {
            sock = socket(AF_INET, SOCK_DGRAM, 0);   //AF_INET:IPV4类型通信;  SOCK_DGRAM: 套接字类别,如流式套接字,原始套接字;
			//sock的返回值是文件描述符;所以sock相当于之前的Open()
            std::cout << "sock: " << sock << std::endl; //默认是3;
			//所以创建套接字本质是打开了一个文件;但是当前只有网络文件信息;所以接下来要bind ip和port信息;
			 
            struct sockaddr_in local;  //绑定是在内核层绑定;
            local.sin_family = AF_INET;
            local.sin_port = htons(port); //主机序列转为网络序列
            local.sin_addr.s_addr = inet_addr(ip.c_str());  //把字符串风格的IP转换成网络IP //ip是string的字符串,所以要转换为char,即用.c_str()
			//关于bind 成功返回0,失败<0;
            if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){ //注意这里&local 为struct sockadd_in类型, 要强转为 struct sockaddr* 
                std::cerr << "bind error!\n" << std::endl;
                exit(1);
            }
        }

        //echo server  服务器已经创建好了 下面收发消息
        void start()
        {
            char msg[64];
            for(;;){
                msg[0] = '\0';
                struct sockaddr_in end_point;
                socklen_t len = sizeof(end_point);
                ssize_t s = recvfrom(sock, msg, sizeof(msg)-1,\ //s是读到数据的长度 // (打开的文件, 缓冲区, 期望读多少数据)
                        0, (struct sockaddr*)&end_point, &len);  //最后两个是输出型参数和输入输出型参数,发送方地址, 发送了多长实际接收了多长
						
                if(s > 0){
                    msg[s] = '\0';
                    std::cout <<"client# " << msg << std::endl;
                    std::string echo_string = msg;
                    echo_string += " [server echo!]";
                    sendto(sock, echo_string.c_str(), echo_string.size(), 0,\
                            (struct sockaddr*)&end_point, len);
                }
            }
        }
        ~udpServer()
        {
            close(sock);
        }
};

Client.hpp

#pragma once

#include <iostream>
#include <string>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

class udpClient{
    private:
        std::string ip;
        int port;
        int sock;
    public:
        //ip,port? server ip,port!!!
        udpClient(std::string _ip="127.0.0.1", int _port=8080)
            :ip(_ip), port(_port)
        {

        }
        void initClient()
        {
            sock = socket(AF_INET, SOCK_DGRAM, 0);
            std::cout << "sock: " << sock << std::endl;
            //客户端不需要bind,但需要IP port  ;
           // struct sockaddr_in local;
           // local.sin_family = AF_INET;
           // local.sin_port = htons(port);
           // local.sin_addr.s_addr = inet_addr(ip.c_str());

           // if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){
           //     std::cerr << "bind error!\n" << std::endl;
           //     exit(1);
           // }
        }

        //echo server
        void start()
        {
          //  char msg[64];
            std::string msg;
            struct sockaddr_in peer;  //peer 远端
            peer.sin_family = AF_INET;
            peer.sin_port = htons(port);
            peer.sin_addr.s_addr = inet_addr(ip.c_str());

            for(;;){
                std::cout << "Please Enter# ";
                std::cin >> msg;
                if(msg == "quit"){
                    break;
                }
				//客户端先发消息
                sendto(sock, msg.c_str(), msg.size(), 0, (struct sockaddr*)&peer, sizeof(peer));

                char echo[128]; //用于存放接收的消息
                ssize_t s = recvfrom(sock, echo, sizeof(echo)-1, 0, nullptr, nullptr);  //echo:缓冲区
                if(s >0){										    //发送方
                    echo[s] = 0;
                    std::cout << "server# " << echo << std::endl;
                }

          //      msg[0] = '\0';
          //      struct sockaddr_in end_point;
          //      socklen_t len = sizeof(end_point);
          //      ssize_t s = recvfrom(sock, msg, sizeof(msg)-1,\
          //              0, (struct sockaddr*)&end_point, &len);
          //      if(s > 0){
          //          msg[s] = '\0';
          //          std::cout <<"client# " << msg << std::endl;
          //          std::string echo_string = msg;
          //          echo_string += " [server echo!]";
          //          sendto(sock, echo_string.c_str(), echo_string.size(), 0,\
          //                  (struct sockaddr*)&end_point, len);
          //      }
            }
        }
        ~udpClient()
        {
            close(sock);
        }
};

Server.cc

#include "udpServer.hpp"

int main()
{
    udpServer *up = new udpServer();
    up->initServer();
    up->start();

    delete up;
}

Client.cc

#include "udpClient.hpp"
int main()
{
    udpClient uc;  //new或者不new都可以 建议new
    uc.initClient();
    uc.start();

    return 0;
}

结果展示:
在这里插入图片描述

二、基于UDP协议 简单在线翻译

在这里插入图片描述
在这里插入图片描述

代码展示

Makefile


FLAG=-std=c++11

.PHONY:all
all:udpClient udpServer

udpClient:udpClient.cc
	g++ -o $@ $^ $(FLAG) -static
udpServer:udpServer.cc
	g++ -o $@ $^ $(FLAG)

.PHONY:clean
clean:
	rm -f udpClient udpServer

server.hpp

#pragma once

#include <iostream>
#include <cstdio>
#include <string>
#include <map>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

class udpServer{
    private:
//        std::string ip;
        int port;
        int sock;
        std::map<std::string, std::string> dict;
    public:
        udpServer(int _port=8080)
            :port(_port)
        {
            dict.insert(std::pair<std::string, std::string>("apple", "苹果,是一种水果!"));
            dict.insert(std::pair<std::string, std::string>("banana", "香蕉,是一种水果!"));
            dict.insert(std::pair<std::string, std::string>("student", "学生"));
        }
        void initServer()
        {
            sock = socket(AF_INET, SOCK_DGRAM, 0);
            std::cout << "sock: " << sock << std::endl;
            struct sockaddr_in local;
            local.sin_family = AF_INET;
            local.sin_port = htons(port);
            //local.sin_addr.s_addr = inet_addr(ip.c_str());
            local.sin_addr.s_addr = INADDR_ANY;  //表示可以接收任意IP地址

            if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){
                std::cerr << "bind error!\n" << std::endl;
                exit(1);
            }
        }

        //echo server
        void start()
        {
            char msg[64];
            for(;;){
                msg[0] = '\0';
                struct sockaddr_in end_point;
                socklen_t len = sizeof(end_point);
                ssize_t s = recvfrom(sock, msg, sizeof(msg)-1,\
                        0, (struct sockaddr*)&end_point, &len);
                //分析命令
                //fork
                //dup2()1, socket
                //exec*(cmd)? 
                if(s > 0){
                    char buf[16];
                    sprintf(buf, "%d", ntohs(end_point.sin_port));

                    std::string cli = inet_ntoa(end_point.sin_addr); //将主机地址转换位点分十进制;
                    cli += ":";
                    cli += buf;


                    msg[s] = '\0';
                    std::cout << cli << "# " << msg << std::endl;
                    std::string echo = "unknow";
                    auto it = dict.find(msg);
                    if(it != dict.end()){
                        echo = dict[msg];
                    }

                    //echo_string += " [server echo!]";
                    sendto(sock, echo.c_str(), echo.size(), 0,\
                            (struct sockaddr*)&end_point, len);
                }
            }
        }
        ~udpServer()
        {
            close(sock);
        }
};

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

client.hpp

#pragma once

#include <iostream>
#include <string>
#include <unistd.h>
#include <stdlib.h>+
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

class udpClient{
    private:
        std::string ip;
        int port;
        int sock;
    public:
        //ip,port? server ip,port!!!
        udpClient(std::string _ip="127.0.0.1", int _port=8080)
            :ip(_ip), port(_port)
        {

        }
        void initClient()
        {
            sock = socket(AF_INET, SOCK_DGRAM, 0);
            std::cout << "sock: " << sock << std::endl;
           // struct sockaddr_in local;
           // local.sin_family = AF_INET;
           // local.sin_port = htons(port);
           // local.sin_addr.s_addr = inet_addr(ip.c_str());

           // if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){
           //     std::cerr << "bind error!\n" << std::endl;
           //     exit(1);
           // }
        }

        //echo server
        void start()
        {
          //  char msg[64];
            std::string msg;
            struct sockaddr_in peer;
            peer.sin_family = AF_INET;
            peer.sin_port = htons(port);
            peer.sin_addr.s_addr = inet_addr(ip.c_str());

            for(;;){
                std::cout << "Please Enter# ";
                std::cin >> msg;
                if(msg == "quit"){
                    break;
                }

                sendto(sock, msg.c_str(), msg.size(), 0, (struct sockaddr*)&peer, sizeof(peer));
				//发送后要接收消息;
                char echo[128];
                ssize_t s = recvfrom(sock, echo, sizeof(echo)-1, 0, nullptr, nullptr);
                if(s >0){
                    echo[s] = 0;
                    std::cout << "server# " << echo << std::endl;
                }

          //      msg[0] = '\0';
          //      struct sockaddr_in end_point;
          //      socklen_t len = sizeof(end_point);
          //      ssize_t s = recvfrom(sock, msg, sizeof(msg)-1,\
          //              0, (struct sockaddr*)&end_point, &len);
          //      if(s > 0){
          //          msg[s] = '\0';
          //          std::cout <<"client# " << msg << std::endl;
          //          std::string echo_string = msg;
          //          echo_string += " [server echo!]";
          //          sendto(sock, echo_string.c_str(), echo_string.size(), 0,\
          //                  (struct sockaddr*)&end_point, len);
          //      }
            }
        }
        ~udpClient()
        {
            close(sock);
        }
};

server.cc

#include "udpServer.hpp"
8080
void Usage(std::string proc)
{
    std::cout << "Usage: " << proc << " port" <<std::endl;
}

//./udpServer ip port
int main(int argc, char *argv[])  //  指针数组
{
    if(argc != 2){      //检查合法性;argc表示指针数组的元素个数。这里是2个:./server  8080
        Usage(argv[0]);
        exit(1);
    }
    udpServer *up = new udpServer(atoi(argv[1]));
    up->initServer();
    up->start();

    delete up;
}

client.cc

#include "udpClient.hpp"

void Usage(std::string proc)
{
    std::cout <<"Usage: "<< proc << " svr_ip svr_port" << std::endl;
}

int main(int argc, char *argv[])
{
    if(argc != 3){
        Usage(argv[0]);
        exit(1);
    }
    udpClient uc(argv[1], atoi(argv[2]));
    uc.initClient();
    uc.start();

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
基恩士KV7500是一款广泛应用于工业自动化控制系统的高性能控制器。其中的套通讯功能,是指KV7500控制器通过套协议实现与其他设备之间的数据交换和通信。 套通讯是一种常见的网络通讯方式,它通过建立起网络连,实现数据的传输和交换。在KV7500中,套通讯可以通过以太网口或串口口,与其他设备进行通信。 使用KV7500的套通讯功能,可以实现以下应用: 1. 数据采集和监测:KV7500可以通过套通讯与传感器、监测设备等进行数据交换,实时采集和监测环境参数、设备状态等信息。 2. 远程控制和操作:通过套通讯,可以实现对远程设备的控制和操作,例如对远程设备进行开关、调节等操作。 3. 数据传输和共享:KV7500可以通过套通讯与其他控制器、服务器等设备之间进行数据传输和共享,实现数据的集中管理和分析。 为了使用KV7500的套通讯功能,需要进行以下设置: 1. 配置网络参数:包括IP地址、子网掩码、网关等,确保KV7500能够与其他设备建立网络连。 2. 配置通讯协议:选择适合的套通讯协议,如TCP/IP或UDP等,根据实际需求进行配置。 3. 编写通讯程序:通过KV7500的编程软件,编写套通讯的相关程序,实现数据的读取、发送和处理等功能。 总之,基恩士KV7500套通讯功能具有灵活、高效、稳定等特点,可以满足工业自动化控制系统中的数据交换和通信需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值