套接字编程:UDP通信程序

简介: 套接字编程:UDP通信程序

一、服务端


1.编写流程


1.1 创建套接字


       在内核中创建socket结构体,将进程与网卡关联起来。


1.2 为套接字绑定地址信息


       给创建的套接字socket结构体描述源端地址信息。


作用:


       1)告诉系统,网卡收到的那条数据应该交给我来处理;


       2)当发生数据时,使用绑定的地址信息作为源端地址信息。


1.3 接收数据


       从socket的接收缓冲区中取出数据。


1.4 发送数据


       把要发送的数据放到发送缓冲区中。


1.5 关闭套接字


2. 代码实现


#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<netinet/in.h> //struct_sockaddr_in 结构
#include<arpa/inet.h> //字节序转换接口
#include<sys/socket.h> //socket接口头文件
#include<string.h>
int main() {
  //1.创建套接字
  int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if (sockfd < 0) {
    perror("Create socket error!");
    return -1;
  }
  //2.为套接字绑定地址信息
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(8888);
  addr.sin_addr.s_addr = inet_addr("192.168.247.128");
  socklen_t len = sizeof(struct sockaddr_in);
  int ret = bind(sockfd, (struct sockaddr*)&addr, len);//绑定地址信息
  if (ret < 0) {
    perror("bind error!");
    return -1;
  }
  //接收&发送 数据
  while (1) {
    //3.接收数据
    char buf[1024] = {0};
    struct sockaddr_in client;//保存发送方的地址信息
    ret = recvfrom(sockfd, buf, 1023, 0, (struct sockaddr*)&client, &len);
    if (ret < 0) {
      perror("recvfrom error!");
      close(sockfd);
      return -1;
    }
    //打印客户端的信息
    printf("client:%s 端口:%d 数据:%s\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port), buf);
    //4.发送数据
    printf("server send: ");
    fflush(stdout);
    char data[1024] = {0};
    fgets(data, 1023, stdin);
    ret = sendto(sockfd, data, strlen(data), 0, (struct sockaddr*)&client, len);
    if (ret < 0) {
      perror("sendto error!");
      close(sockfd);
      return -1;
    }
  }
  //5.关闭套接字
  close(sockfd);
  return 0;
}


二、客户端


1.编写流程


1.1 创建套接字


1.2 为套接字绑定地址信息(不推荐)

       客户端并不推荐主动绑定地址。


原因:


       1)绑定之后,程序只能启动一个;


       2)客户端并不需要固定使用某个地址。


1.3 向服务器发送数据


       发送数据前,若socket没有绑定指定地址,则系统会自动选择一个合适的地址信息进行绑定。


1.4 接收数据


1.5 关闭套接字


2. 代码实现


       通过封装一个客户端类,可以更加便捷的创建多个客户端。


2.1 客户端头文件-类封装


#include<iostream>
#include<string>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/socket.h>
//封装UDPsocket类
//通过类实例化对象,调用成员接口,简单的完成服务器与客户端搭建
class UDPsocket {
  private:
    int _sockfd;
  public:
    UDPsocket() : _sockfd(-1) {}
    ~UDPsocket() {if(_sockfd != -1) close(_sockfd);}
    //1.创建套接字
    bool Socket() {
      _sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
      if (_sockfd < 0) {
        perror("create socket error!");
        return false;
      }
      return true;
    }
    //2.绑定地址信息
    bool Bind(const std::string &ip, uint16_t port) {
      struct sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_port = htons(port);
      addr.sin_addr.s_addr = inet_addr(ip.c_str());
      socklen_t len = sizeof(struct sockaddr_in);
      int ret = bind(_sockfd, (struct sockaddr*)&addr, len);
      if (ret < 0) {
        perror("bind error!");
        return false;
      }
      return true;
    }
    //3.发送数据
    bool Send(const std::string &data, const std::string &ip, uint16_t port) {
      struct sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_port = htons(port);
      addr.sin_addr.s_addr = inet_addr(ip.c_str());
      socklen_t len = sizeof(struct sockaddr_in);
      int ret = sendto(_sockfd, data.c_str(), data.size(), 0, (struct sockaddr*)&addr, len);
      if (ret < 0) {
        perror("sendto error!");
        return false;
      }
      return true;
    }
    //4.接收数据
    bool Recve(std::string *buf, std::string *ip = NULL, uint16_t *port = NULL) {
      struct sockaddr_in addr;
      socklen_t len = sizeof(struct sockaddr_in);
      char temp[4096] = {0};
      int ret = recvfrom(_sockfd, temp, 4095, 0, (struct sockaddr*)&addr, &len);
      if (ret < 0) {
        perror("recvfrom error!");
        return false;
      }
      if (ip != NULL) *ip = inet_ntoa(addr.sin_addr);
      if (port != NULL) *port = ntohs(addr.sin_port);
      *buf = temp;
      return true;
    }
    //5.关闭套接字
    bool Close() {
      if (_sockfd != -1) close(_sockfd);
      return true;
    }
};


2.2 客户端实现


#include "udp_socket.hpp"
#define CHECK_RETURN(x) if ((x) == false) {return -1;}
int main(int argc, char *argv[]) {
  if (argc != 3) {
    std::cout<<"Usage: ./udp_client ip port"<< std::endl;
    std::cout<<"Server address!"<< std::endl;
    return -1;
  }
  UDPsocket sock;//创建客户端对象
  std::string srv_ip = argv[1];
  int srv_port = std::stoi(argv[2]);
  //1.创建套接字
  CHECK_RETURN(sock.Socket());
  //2. 绑定地址信息----客户端不推荐
  while (1) {
    std::cout<<"client send:";
    fflush(stdout);
    std::string buf;
    std::cin>>buf;
    //3.发送数据
    CHECK_RETURN(sock.Send(buf, srv_ip, srv_port));
    //4.接收数据
    buf.clear();
    CHECK_RETURN(sock.Recve(&buf));
    std::cout<<"server reply:" << buf << std::endl;
  }
  //5.关闭套接字
  CHECK_RETURN(sock.Close());
  return 0;;
}


相关文章
|
6月前
|
网络协议 Java API
基于UDP/TCP实现客户端服务器的网络通信程序
基于UDP/TCP实现客户端服务器的网络通信程序
|
29天前
|
网络协议 Linux 网络性能优化
Linux C/C++之TCP / UDP通信
这篇文章详细介绍了Linux下C/C++语言实现TCP和UDP通信的方法,包括网络基础、通信模型、编程示例以及TCP和UDP的优缺点比较。
35 0
Linux C/C++之TCP / UDP通信
|
6月前
|
网络协议 算法 Java
【Java网络编程】网络编程概述、UDP通信(DatagramPacket 与 DatagramSocket)
【Java网络编程】网络编程概述、UDP通信(DatagramPacket 与 DatagramSocket)
67 3
|
2月前
|
C语言
C语言 网络编程(七)UDP通信创建流程
本文档详细介绍了使用 UDP 协议进行通信的过程,包括创建套接字、发送与接收消息等关键步骤。首先,通过 `socket()` 函数创建套接字,并设置相应的参数。接着,使用 `sendto()` 函数向指定地址发送数据。为了绑定地址,需要调用 `bind()` 函数。接收端则通过 `recvfrom()` 函数接收数据并获取发送方的地址信息。文档还提供了完整的代码示例,展示了如何实现 UDP 的发送端和服务端功能。
|
3月前
|
网络协议 数据处理 C语言
网络编程进阶:UDP通信
网络编程进阶:UDP通信
156 0
|
3月前
|
C语言
【C语言】UDP通信
【C语言】UDP通信
36 0
|
4月前
|
网络协议 网络架构
【网络编程入门】TCP与UDP通信实战:从零构建服务器与客户端对话(附简易源码,新手友好!)
在了解他们之前我们首先要知道网络模型,它分为两种,一种是OSI,一种是TCP/IP,当然他们的模型图是不同的,如下
184 1
|
4月前
|
网络协议 Java 数据处理
(一)Java网络编程之计网基础、TCP-IP协议簇、TCP、UDP协议及腾讯QQ通信原理综述
就目前而言,多数网络编程的系列的文章都在围绕着计算机网络体系进行阐述,但其中太多理论概念,对于大部分开发者而言,用途甚微。因此,在本系列中则会以实际开发者的工作为核心,从Java程序员的角度出发,详细解读Java的网络编程核心内容。
|
6月前
|
网络协议 安全 Java
网络编程、网络编程的三要素、TCP/UDP通信、三次握手和四次挥手
网络编程、网络编程的三要素、TCP/UDP通信、三次握手和四次挥手
55 1
网络编程、网络编程的三要素、TCP/UDP通信、三次握手和四次挥手
|
4月前
基于QT实现的QQ聊天简易版(UDP通信版)
源码已经给小伙伴们整理好了,微信搜索 嵌入式工程之家 关注公众号回复 QQ 即可获得源码和详细操作指示哦~
100 0