套接字编程: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实现客户端服务器的网络通信程序
|
6天前
|
网络协议 算法 Java
【Java网络编程】网络编程概述、UDP通信(DatagramPacket 与 DatagramSocket)
【Java网络编程】网络编程概述、UDP通信(DatagramPacket 与 DatagramSocket)
19 3
|
6天前
|
存储 网络协议 算法
【探索Linux】P.28(网络编程套接字 —— 简单的UDP网络程序模拟实现)
【探索Linux】P.28(网络编程套接字 —— 简单的UDP网络程序模拟实现)
16 0
|
6天前
|
存储 网络协议 关系型数据库
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
|
8月前
|
网络协议 Java
Java UDP通信详解
UDP(User Datagram Protocol)是一种无连接的网络传输协议,它不像TCP那样需要建立连接和维护状态,因此更加轻量级。UDP适用于那些对数据传输的实时性要求较高,可以容忍一定数据丢失的场景。本文将详细介绍Java中如何使用UDP协议进行网络通信,包括UDP套接字、数据传输、服务器和客户端的创建等。
137 0
|
9月前
|
Python
【从零学习python 】73. UDP网络程序-发送数据
【从零学习python 】73. UDP网络程序-发送数据
46 0
|
6天前
|
存储 网络协议 安全
网络编程『socket套接字 ‖ 简易UDP网络程序』
网络编程『socket套接字 ‖ 简易UDP网络程序』
83 0
|
6天前
UDP通信程序练习(实现模拟聊天室)
UDP通信程序练习(实现模拟聊天室)
52 0
|
6天前
|
存储 网络协议 Java
UDP通信程序的详细解析
2.UDP通信程序 2.1 UDP发送数据 Java中的UDP通信 UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个Socket只是发送,接收数据的对象,因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念
43 0
|
5月前
|
C语言
UDP通信原理及网络编程
UDP通信原理及网络编程
54 0