套接字编程_udp

套接字编程_udp

1.什么是套接字:
TCP用主机的IP地址加上主机上的端口号作为TCP连接的端点,这种端点就叫做套接字(socket)或插口。
套接字用(IP地址:端口号)表示。
它是网络通信过程中端点的抽象表示,包含进行网络通信必需的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
(源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字。其用于标识客户端请求的服务器和服务。)

2.套接字是用来干什么的:
套接字,是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。
3.传输层有两个协议:tcp/udp

udp:

用户数据报协议:无连接,不可靠,面向数据报;应用场景:数据实时性大于安全性的场景。(像视频传输),有最大长度限制的数据传输服务。

udp网络通信程序流程:
在这里插入图片描述
操作系统对于接收到的数据,判断目的地址信息,去内核socket容器
一 一查找。
1.找到了,则将这个数据放入这个socket的接收缓冲区中。
2.没找到,则这个数据直接被丢弃。

socket接口介绍:
1.创建套接字

int socket(int domain, int type, int protocol)

domain:地址域 ---- 不同的网络地址结构 AF-INET (IPv4地址域)
type: 套接字类型 — 流式套接字/数据报套接字
流式套接字: 一种有序的,可靠的,双向的,基于连接的字节流传输 SOCK_STREAM
数据报套接字:无连接的,不可靠,有最大长度限制的传输 SOCK_DGRAM
protocol:使用协议 0----不同套接字类型下的默认协议:流式套接字tcp/数据报套接字默认是udp
IPPROTO_TCP — tcp协议 IPPROTO_UDP — udp协议
返回值:返回套接字的操作句柄-----文件描述符

2.为套接字绑定地址信息

int bind(int sockfd, struct sockaddr* addr, socklen_t len);

sockfd:创建套接字返回的操作句柄。
addr: 要绑定的地址信息结构
len:地址信息的长度
返回值:成功返回0;失败返回-1。

3.发送数据

int sendto(int sockfd,char* data, int data_len, int flag, struct sockaddr *dest_addr, socklen_t addr_len);

sockfd:套接字操作句柄,发送数据就是将数据拷贝到内核socket发送缓冲区中
data: 要发送的数据的首地址
data_len: 要发送的数据的长度
flag: 选项参数 默认为0—表示当前操作时阻塞操作 MSG_DONTWAIT —设置为非阻塞
如果发送数据时,socket发送缓冲区已经满了,则0默认阻塞等待;MSG_DONTWAIT就会立即报错返回。
dest_addr: 目的端地址信息结构—表示数据要发送给谁
dest_len: 地址信息结构长度
返回值:成功则返回实际发送的数据节数; 失败返回-1;

4.接受数据

扫描二维码关注公众号,回复: 9864850 查看本文章
int recvfrom(int sockfd, char *buf,int len, int flag, struct sockaddr*src_addr, socklen_t* addr_len);

sockfd:套接字操作句柄
buf: 缓冲区首地址,用于存放接收到的数据,从内核socket接收缓冲区中取出数据放入这个buf用户态缓冲区。
len: 用户想要读取的数据长度,但不能大于buf缓冲区的长度。
flag: 0 —默认阻塞操作–若缓冲区中没有数据则一直等待 MSG_DONTWAIT—非阻塞
src_addr: 接收到的数据发送端地址
addr_len :用于指定想要获取多长的地址信息
返回值: 成功返回实际接收到的数据字节长度; 失败返回-1;

5.关闭套接字

int close(int fd);

6.代码:
1.udpsocket.hpp

#pragma once
#include<iostream>
#include<cstdio>
#include<string>
#include<unistd.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/socket.h>
class UdpSocket
{
public:
    UdpSocket():_sockfd(-1) {

    }
    bool Socket() {
        _sockfd =  socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP);
        if(_sockfd < 0) {
            perror("socket error");
            return false;
        }
        return true;
    }

    bool Bind(const std::string &ip, uint32_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;
    }
    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());

        int ret;
        socklen_t len = sizeof(struct sockaddr_in);
        ret = sendto(_sockfd, data.c_str(), data.size(), 0, (struct sockaddr*)&addr, len);
        if(ret < 0) {
            perror("sendto error");
            return false;
        }
        return true;
    }
    bool Recv(std::string *buf, std::string *ip = NULL, uint16_t *port = NULL) {

        struct sockaddr_in addr;
        socklen_t len = sizeof(struct sockaddr_in);
        int ret;
        char tmp[4096] = {0};
        ret = recvfrom(_sockfd, tmp, 4096, 0, (struct sockaddr*)&addr, &len);
        if(ret < 0) {
            perror("recvfrom error");
            return -1;
        }
        buf->assign(tmp, ret);
        if(ip != NULL){
            *ip = inet_ntoa(addr.sin_addr);
        }
        if(port != NULL) {
            *port = ntohs(addr.sin_port);
        }
        return true;
    }
    void Close() {
        close(_sockfd);
        _sockfd = -1;
        return ;
    }

private:
    int _sockfd;

};

2.udp_cli.cc

#include <iostream>
#include<stdlib.h>
#include "udpsocket.hpp"

#define CHECK_RET(q) if((q)==false){return -1;}

int main(int argc, char *argv[]) {
    if(argc != 3) {
        printf("em: ./udp_cli 192.168.122.132 9000\n");
        return -1;
    }
    std::string ip_addr = argv[1];
    uint16_t port_addr = atoi(argv[2]);
    UdpSocket sock;
    CHECK_RET(sock.Socket());

    while(1) {
        std::cout << "client say:";
        fflush(stdout);
        std::string buf;
        std::cin >> buf;
        sock.Send(buf, ip_addr, port_addr);

        buf.clear();
        sock.Recv(&buf);
        std::cout << "server say:" << buf << std::endl;
    }
    sock.Close();

    return 0;
}

3.udp_srv.cc

#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include "udpsocket.hpp"
int main(int argc, char *argv[]){

    if(argc != 3) {
     printf("./udp_cli.srv ip port em:./udp_srv 192.168.122.132 9000\n");
     return -1;
    }
    const char *ip_addr = argv[1];
    uint16_t port_addr = atoi(argv[2]);

    int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(sockfd < 0) {
        perror("socket error");
        return -1;
    }
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port_addr);
    addr.sin_addr.s_addr = inet_addr(ip_addr);
    socklen_t len = sizeof(struct sockaddr_in);
    int ret = bind(sockfd, (struct sockaddr*)&addr, len);

    if(ret < -1) {
        perror("bind error");
        return -1;
    }
    while(1){
        char buf[1024] = {0};
        struct sockaddr_in cliaddr;
        socklen_t len = sizeof(struct sockaddr_in);

        int ret = recvfrom(sockfd, buf, 1023, 0, (struct sockaddr*)&cliaddr, &len);
        if(ret < 0){
            perror("recefrom error");
            close(sockfd);
            return -1;
        }
      printf("client say: %s\n", buf);

      printf("server say: ");
      fflush(stdout);
      memset(buf, 0x00, 1024);
      scanf("%s" ,buf);

      ret = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr*)&cliaddr, len);
      if(ret < 0) {
          perror("sendto error");
          close(sockfd);
          return -1;
      }
    }
    close(sockfd);
}
发布了29 篇原创文章 · 获赞 12 · 访问量 1110

猜你喜欢

转载自blog.csdn.net/childemao/article/details/104895007