【Linux】网络编程套接字socket

    科技2025-10-25  10

    1.套接字socket编程:网络通信程序的编写

    网络通信程序的编写使用的都是套接字接口 网络通信程序的编写:TCP/IP五层中应用层是面向程序员的一层,应用层的协议都是程序员自己订立,应用层处理完毕后,将数据交给操作系统,进行传输层开始往下的封装。 传输层的典型协议:UDP/TCP  

    2.UDP协议和TCP协议的区别

    UDP协议:用户数据包协议-----无连接的,不可靠的,面向数据包的一种传输方式(无法提供可靠传输,但是传输速度快)–视频传输 TCP协议:传输控制协议----基于连接的,可靠的,面向字节流的一种传输方式(提供可靠传输,但是传输速度较慢)–普通的文件传输  

    3.UDP通信程序的编写

    在网络通信中,都是端与端之间的通信,两台主机的两个进程间的通信,并且通信两端有一种叫法:

    客户端:通信两端中,首先主动发起请求的一端 服务端:通信两端中,首先被动接受请求的一端

     

    4.通信流程

    server(服务端)1.在程序中创建套接字—使进程与网卡之间通过套接字建立联系2.为套接字绑定地址信息 ①地址信息:IP地址和端口 ②每一条网络中的数据都要包含:源端IP,PORT,对端IP,PORT ③接收端:告诉操作系统发往这个主机的那个端口的数据应该交给我处理 ④发送端:告诉操作系统,发送的这条数据的源端地址是什么 ⑤就是在创建套接字创建的socket结构体中描述地址信息  3.服务端首先接收数据 ①创建套接字,实际上在内核中创建了一个结构体–socket,socket中会有两个缓冲区(发送/接收) ②一旦网卡接收到数据,这时候操作系统会根据数据中的目的地址信息,去socket列表中进行匹配,这个数据应该放到谁的接收缓冲区中 ③接收数据,只是通过接收接口直接从指定的socket接收缓冲区中取出数据  4.发送数据:将数据放到指定socket的发送缓冲区中,操作系统会在何时的时候,从缓冲分区中取出数据进行封装,最后传输出去5.关闭套接字,释放资源   client(客户端)1.创建套接字,在内核中创建socket结构体2.为套接字绑定地址信息(不推荐) ①刻画段不推荐程序员主动绑定地址,因为一个端口执行被一个进程占用,一旦要绑定的端口已经被使用,则会绑定失败 ②尽可能的避免了地址冲突的概率

     

    5.接口介绍

    ① 创建套接字:在内核中创建socket结构体 int socket(int domain, int type, int protocol);

    domain:地址域类型(地址有各种结构—ipv4,ipv6,local)–表示这是一个什么样通信套接字 AF_INET—ipv4协议版本的地址域

    type:套接字类型(SOCKET_STREAM—流式套接字—默认协议是tcp,SOCKET_DGRAM—数据报套接字—默认是udp)

    protocol:协议类型—0表示要解字类型的默认协议;IPPROTO_TCP-6 / IPPROT_UDP-17

    返回值:返回套接字操作句柄—文件描述符;失败返回-1

     

    ② 为套接字绑定地址信息:在创建的socket结构体中描述源端的地址信息,告诉操作系统那些数据放到自己的接收缓冲区int bind(int sockfd, struct sockaddr*addr, socklen_t len)sockfd:创建套接字返回的操作句柄addr:要绑定的地址信息----struct sockaddr 通用地址结构(通常不用这个)–len:地址信息长度ipv4使用的是struct sockaddr_in{sin_family—地址域类型;sin_port—网络字节序端口;sin_addr.s_addr–网络字节序IP地址}

    6.UDP实现

    // udp客户端通信程序 // 1.创建套接字 // 2.绑定地址信息(不推荐) // 3.接收数据 // 4.发送数据 // 5.关闭套接字 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/socket.h> // socket结构头文件 #include <netinet/in.h> // 地址结构头文件 #include <arpa/inet.h> // 网络字节序转换接口头文件 int main(int argc, char* argv[]) { // argc表示运行参数的个数 // argv存储程序的运行参数,运行参数是运行程序的时候,以空格间隔跟在程序后边 // ./udp_cli 192.169.*.* 9000 if(argc != 3) { printf("usage:./udp_cli 192.169.*.* 9000"); return -1; } char* ip = argv[1]; uint16_t port = atoi(argv[2]); // socket(地址域,套接字类型,协议类型) int sockfd = socket(AF_INET,SOCK_DGRAM, IPPROTO_UDP); if(sockfd < 0) { perror("socket perror"); return -1; } // bind(套接字描述符,地址信息,地址信息长度) struct sockaddr_in addr; // 使用的ipv4的地址结构 addr.sin_family = AF_INET; // 地址域类型 addr.sin_port = htons(port); // 网路字节序端口信息-主要使用htons,而不是htonl addr.sin_addr.s_addr = inet_addr(ip); // inet_addr将字符串地址转换为网络字节序整型地址 socklen_t len = sizeof(addr); int ret = bind(sockfd, (struct sockaddr*)&addr, len); if(ret < 0) { perror("bind error"); return -1; } return 0;
    Processed: 0.011, SQL: 9