2024年Linux最新Linux C++ UDP Socket(超详细)_c+(2)

UPD通讯

2. API

详细API请参考:https://pubs.opengroup.org/onlinepubs/007908799/xns/syssocket.h.html

  • 创建套接字的函数是socket()
int socket(int domain, int type, int protocol);

/\*
- 其中 “int domain”参数表示套接字要使用的协议簇,协议簇的在“linux/socket.h”里有详细定义,常用的协议簇:
AF\_UNIX(本机通信)
AF\_INET(TCP/IP – IPv4)
AF\_INET6(TCP/IP – IPv6)

- 其中 “type”参数指的是套接字类型,常用的类型有:
SOCK\_STREAM(TCP流)
SOCK\_DGRAM(UDP数据报)
SOCK\_RAW(原始套接字)

- 最后一个 “protocol”一般设置为“0”,也就是当确定套接字使用的协议簇和类型时,这个参数的值就为0,但是有时候创建原始套接字时,并不知道要使用的协议簇和类型,也就是domain参数未知情况下,这时protocol这个参数就起作用了,它可以确定协议的种类。
socket是一个函数,那么它也有返回值,当套接字创建成功时,返回套接字,失败返回“-1”,错误代码则写入“errno”中。
\*/

// 实例
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/socket.h>
	int sock_fd_tcp;
    int sock_fd_udp;
    sock_fd_tcp = socket(AF_INET, SOCK_STREAM, 0);     // 创建tcp通讯的套接字
    sock_fd_udp = socket(AF_INET, SOCK_DGRAM, 0);	   // 创建udp通讯的套接字
    if(sock_fd_tcp < 0) {
        perror("TCP SOCKET ERROR!\n");
        exit(-1);
     }
 
    if(sock_fd_udp < 0) {
        perror("UDP SOCKET ERROR!\n");
        exit(-1);
     }

  • 地址与端口设置的结构体 sockaddr_in
#include <netinet/in.h>
   
struct sockaddr\_in{
     unsigned short         sin_family;    
     unsigned short int     sin_port;      
     struct in\_addr         sin_addr;      
     unsigned char          sin_zero[8];   
};

struct in\_addr{
     unsigned long     s_addr;
};
/\*
sin\_family表示地址类型,对于基于TCP/IP传输协议的通信,该值只能是AF\_INET;
sin\_prot表示端口号,例如:21 或者 80 或者 27015,总之在0 ~ 65535之间;
sin\_addr表示32位的IP地址,例如:192.168.1.5 或 202.96.134.133;
sin\_zero表示填充字节,一般情况下该值为0;
Socket数据的赋值实例:
\*/
 


// 实例
 struct sockaddr\_in addr;
 
 memset(&addr, 0, sizeof(addr));  // 将结构体清零 主要是sin\_zero表示填充字节为零
 addr.sin_family = AF_INET;		//(TCP/IP – IPv4)
 addr.sin_port = htons(port_out);    // 绑定端口号 htons将一个无符号短整型数值转换为网络字节序
 addr.sin_addr.s_addr = htonl(INADDR_ANY);  // 绑定IP htonl就是把ip字节顺序转化为网络字节顺序

// INADDR\_ANY 泛指机器所有的IP因为有些电脑不只有一个网卡


  • 把名字和套接字相关联 bind()
int bind( int  sockfd,  const struct sockaddr \* addr, socklen_t \* addrlen);
/\*
当用socket()函数创建套接字以后,套接字在名称空间(网络地址族)中存在,但没有任何地址给它赋值。bind()把用addr指定的地址赋值给用文件描述符代表的套接字sockfd。addrlen指定了以addr所指向的地址结构体的字节长度。一般来说,该操作称为“给套接字命名”。

通常,在一个SOCK\_STREAM套接字接收连接之前,必须通过bind()函数用本地地址为套接字命名。
\*/

// 实例
#include <sys/types.h>
#include <sys/socket.h>


sockfd = socket(AF_INET, SOCK_DGRAM, 0);

struct sockaddr\_in addr;
socklen_t addr_len = sizeof(addr);

if (bind(sockfd, (struct sockaddr\*)&addr, addr_len) == -1){
    printf("Failed to bind socket on port %d\n", port_out);
    close(sockfd);
    return false;
}

  • 接受消息的函数recvfrom()
int recvfrom(int sockfd, void \* buf, size_t len, int flags, struct sockaddr \* src_addr, socklen_t \* addrlen);
/\*
recvfrom: 用于接收数据
- sockfd:用于接收UDP数据的套接字;
- buf:保存接收数据的缓冲区地址;
- len:可接收的最大字节数(不能超过buf缓冲区的大小);
- flags:可选项参数,若没有可传递0;
- src\_addr:存有发送端地址信息的sockaddr结构体变量的地址;
- addrlen:保存参数 src\_addr的结构体变量长度的变量地址值。
\*/

  • 发送消息的函数sendto()
int sendto(int sockfd, const void \* buf, size_t len, int flags, const struct sockaddr \* dest_addr, socklen_t addrlen);
/\*
sendto:用于发送数据
- sockfd:用于传输UDP数据的套接字;
- buf:保存待传输数据的缓冲区地址;
- len:带传输数据的长度(以字节计);
- flags:可选项参数,若没有可传递0;
- dest\_addr:存有目标地址信息的 sockaddr 结构体变量的地址;
- addrlen:传递给参数 dest\_addr的地址值结构体变量的长度。
\*/

注意:UDP套接字不会保持连接状态,每次传输数据都要添加目标地址信息,这相当于在邮寄包裹前填写收件人地址。

3.测试程序

  • server
#include<sys/select.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iostream>

int main(){

    //同一台电脑测试,需要两个端口
    int port_in  = 12321;
    int port_out = 12322;
    int sockfd;

    // 创建socket
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(-1==sockfd){
        return false;
        puts("Failed to create socket");
    }

    // 设置地址与端口
    struct sockaddr\_in addr;
    socklen_t addr_len = sizeof(addr);

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;       // Use IPV4
    addr.sin_port = htons(port_out);    //
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
   // Time out
    struct timeval tv;
    tv.tv_sec  = 0;
    tv.tv_usec = 200000;  // 200 ms
    setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char\*)&tv, sizeof(struct timeval));

    // Bind 端口,用来接受之前设定的地址与端口发来的信息,作为接受一方必须bind端口,并且端口号与发送方一致
    if (bind(sockfd, (struct sockaddr\*)&addr, addr_len) == -1){
        printf("Failed to bind socket on port %d\n", port_out);
        close(sockfd);
        return false;
    }

    char buffer[128];
    memset(buffer, 0, 128);

    int counter = 0;
    while(1){
        struct sockaddr\_in src;
        socklen_t src_len = sizeof(src);
        memset(&src, 0, sizeof(src));
	
     // 阻塞住接受消息
        int sz = recvfrom(sockfd, buffer, 128, 0, (sockaddr\*)&src, &src_len);
        if (sz > 0){
            buffer[sz] = 0;
            printf("Get Message %d: %s\n", counter++, buffer);
        }
        else{
            puts("timeout");
        }
    }

    close(sockfd);
    return 0;
}

  • client
#include<sys/select.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iostream>

int main(){
    int port_in  = 12321;
    int port_out = 12322;
    int sockfd;

    // 创建socket
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(-1==sockfd){
        return false;
        puts("Failed to create socket");
    }

    // 设置地址与端口
    struct sockaddr\_in addr;
    socklen_t  addr_len=sizeof(addr);

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;       // Use IPV4
    addr.sin_port   = htons(port_in);    //
    addr.sin_addr.s_addr = htonl(INADDR_ANY);


为了做好运维面试路上的助攻手,特整理了上百道 **【运维技术栈面试题集锦】** ,让你面试不慌心不跳,高薪offer怀里抱!

这次整理的面试题,**小到shell、MySQL,大到K8s等云原生技术栈,不仅适合运维新人入行面试需要,还适用于想提升进阶跳槽加薪的运维朋友。**

![](https://img-blog.csdnimg.cn/img_convert/44b7a744f8b591d160baf837b13709fa.png)

本份面试集锦涵盖了

*   **174 道运维工程师面试题**
*   **128道k8s面试题**
*   **108道shell脚本面试题**
*   **200道Linux面试题**
*   **51道docker面试题**
*   **35道Jenkis面试题**
*   **78道MongoDB面试题**
*   **17道ansible面试题**
*   **60道dubbo面试题**
*   **53道kafka面试**
*   **18道mysql面试题**
*   **40道nginx面试题**
*   **77道redis面试题**
*   **28道zookeeper**

**总计 1000+ 道面试题, 内容 又全含金量又高**

*   **174道运维工程师面试题**

> 1、什么是运维?

> 2、在工作中,运维人员经常需要跟运营人员打交道,请问运营人员是做什么工作的?

> 3、现在给你三百台服务器,你怎么对他们进行管理?

> 4、简述raid0 raid1raid5二种工作模式的工作原理及特点

> 5、LVS、Nginx、HAproxy有什么区别?工作中你怎么选择?

> 6、Squid、Varinsh和Nginx有什么区别,工作中你怎么选择?

> 7、Tomcat和Resin有什么区别,工作中你怎么选择?

> 8、什么是中间件?什么是jdk?

> 9、讲述一下Tomcat8005、8009、8080三个端口的含义?

> 10、什么叫CDN?

> 11、什么叫网站灰度发布?

> 12、简述DNS进行域名解析的过程?

> 13、RabbitMQ是什么东西?

> 14、讲一下Keepalived的工作原理?

> 15、讲述一下LVS三种模式的工作过程?

> 16、mysql的innodb如何定位锁问题,mysql如何减少主从复制延迟?

> 17、如何重置mysql root密码?

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/topics/618542503)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
ived的工作原理?

> 15、讲述一下LVS三种模式的工作过程?

> 16、mysql的innodb如何定位锁问题,mysql如何减少主从复制延迟?

> 17、如何重置mysql root密码?

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/topics/618542503)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux双网卡指的是在一台Linux服务器上同时使用两个网卡进行网络连接。通过配置双网卡,可以实现网络负载均衡、网络冗余和网络隔离等功能。 在Linux系统中,可以使用ifconfig命令查看和设置网卡信息。首先,通过ifconfig命令查看当前系统中存在的网卡接口,然后通过配置文件修改网络接口的配置信息,使得两个网卡同时工作。 在C程序中,可以使用socket函数创建UDP套接字,然后使用bind函数将套接字绑定到一个特定的本地IP地址和端口号上。接着,使用recvfrom函数从UDP套接字中接收数据报文,并使用sendto函数将数据报文发送到指定的目标IP地址和端口号。 在实际应用中,可以使用两个UDP套接字分别监听两个网卡的IP地址和端口号,以实现双网卡的功能。通过套接字的接收和发送函数,可以在不同的网卡上接收和发送数据报文。 另外,还可以通过设置套接字的选项,如SO_REUSEADDR和SO_BINDTODEVICE等,来实现更精细的控制。 综上所述,Linux双网卡和C语言的socket编程可以结合使用,通过配置双网卡实现网络负载均衡和网络隔离等功能,并使用UDP套接字进行数据的接收和发送。 ### 回答2: Linux双网卡C语言Socket UDP是指在Linux系统下,基于C语言编程,使用SocketUDP协议进行网络通信的双网卡配置。 网卡是计算机连接网络的一种硬件设备,有时我们需要使用多个网卡来实现更高效的网络通信。在Linux系统中,我们可以通过配置双网卡来实现此目的。 使用C语言编程,我们可以使用Socket库函数来进行网络通信。Socket是一种能够在不同计算机之间进行通信的API接口,可以用于UDP、TCP等网络协议。 UDP是用户数据报协议,它是一种无连接的、不可靠的传输协议,适用于一对一或多对一的通信。UDP在传输数据时效率高,但无法保证数据的可靠性和顺序性。 在双网卡配置中,我们可以使用C语言编写程序,通过SocketUDP协议进行通信。首先,我们需要调用Socket函数创建一个套接字,并使用bind函数将套接字绑定到一个特定的IP地址和端口号上。然后,我们可以使用recvfrom函数接收来自其他计算机的数据,并使用sendto函数将数据发送给其他计算机。 通过配置两个不同的网卡,我们可以利用双网卡进行双向通信。例如,我们可以将一个网卡连接到局域网,另一个网卡连接到互联网,这样就可以实现局域网和互联网之间的数据传输。 总之,Linux双网卡C语言Socket UDP是指在Linux系统下,利用C语言编程,通过Socket库函数和UDP协议进行双网卡配置和网络通信的技术。这种技术可以实现高效的双向数据传输,并适用于一对一或多对一的通信场景。 ### 回答3: Linux 双网卡 c socket UDP 是指在 Linux 操作系统中,使用 C 编程语言编写的程序,通过 Socket 编程接口,使用 UDP 协议进行网络通信。 双网卡是指计算机系统中同时安装了两块或多块网卡,通过这些网卡可以连接到不同的网络。在使用双网卡的情况下,我们可以在程序中指定使用哪一块网卡进行数据传输,实现数据的接收和发送。在使用双网卡的环境下,程序可以同时监听多个网络上的数据包,并且可以选择性地进行数据的处理。 Socket 是一种网络编程的接口,是一种软件接口,用于支持进程间的网络通信。在 C 语言中,我们使用 Socket 编程接口来创建网络连接,发送和接收数据。通过 Socket 编程接口,我们可以轻松地实现各种网络通信方式,包括 TCP、UDP 以及其他协议。 UDP 是用户数据报协议(User Datagram Protocol)的缩写,它是一种无连接的、不可靠的传输协议。与 TCP 不同,UDP 不需要在传输之前建立连接,直接将数据通过 UDP 数据包发送给目标主机。由于 UDP 无连接且不可靠,所以它的传输速度比 TCP 快,但是在传输过程中可能会出现数据丢失或者乱序的问题。在使用 UDP 进行网络通信时,我们需要使用程序来处理这些问题,确保数据的可靠性。 总结来说,Linux 双网卡 C Socket UDP 是指在 Linux 操作系统中,通过 C 编程语言编写的程序,使用 Socket 编程接口,利用 UDP 协议进行网络通信。在双网卡环境下,程序可以指定使用哪一块网卡进行数据传输,并且可以实现数据的接收和发送。同时,程序也需要处理 UDP 协议带来的数据丢失或者乱序等问题,确保数据的可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值