socket编程(2024超级详细、Linux)

前言

本文是作者在学习linux网络编程的时候所写的学习笔记,同时方便巩固自己学习的知识和网友们一起分享,尚若发现有什么不对的地方,欢迎指正。

一、网络编程(socket)

1.网络

网络是指将多个计算机或设备通过通信链路连接起来,以实现信息传输和资源共享的系统。网络可以是局域网(LAN),用于连接同一地理位置范围内的设备,也可以是广域网(WAN),用于连接不同地理位置范围内的设备。通过网络,用户可以通过电子邮件、网页浏览、文件传输等方式进行信息交流和资源共享。网络的基础是互联网,它是全球范围内的计算机网络,由各种硬件设备、协议和技术组成。互联网使得人们可以在全球范围内进行通信和访问各种信息资源。网络的发展和应用对现代社会的各个领域都有着重要的影响,包括通信、商务、教育、娱乐等。

2.socket()函数 用来创建套字节

2.1 Linux系统下的C语言socket函数原型

// Create a socket
// Parameters:
//   domain: communication domain (e.g., AF_INET for IPv4)
//   type: socket type (e.g., SOCK_STREAM for TCP)
//   protocol: specific protocol (e.g., 0 for default protocol)
// Return value:
//   If successful, returns the socket file descriptor; otherwise, returns -1
int socket(int domain, int type, int protocol);

2.2 Linux系统下的C语言socket位于哪个头文件

#include <sys/socket.h>

2.3 Linux系统下的C语言socket函数参数说明

函数是在网络编程中用于创建套接字的系统调用函数。套接字是实现网络通信的一种机制,它可以用于在不同的计算机之间进行数据传输。

int socket(int domain, int type, int protocol);
  • domain :指定套接字的地址族,常见的有 AF_INET (IPv4)和 AF_INET6 (IPv6)。
  • type :指定套接字的类型,常见的有 SOCK_STREAM (面向连接的流套接字)和 SOCK_DGRAM (无连接的数据报套接字)。
  • protocol :指定套接字使用的协议,通常为0,表示使用默认协议。

2.4 socket里面的domain说明

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

下面我将列举出15个协议族,并且以表格的形式列举出来。注意,这只是一些常见的通信域,实际上还有其他更多的特定协议族可供选择:
man page里面数字的含义,即ip(7)之中7的含义

Protocol Family Name(协议族名字)Description(说明)Chinese(中文)man page(手页册)Commonly Used
AF_INETIPv4 Internet protocolsIPv4网络协议ip(7)*
AF_INET6IPv6 Internet protocolsIPv6网络协议ipv6(7)*
AF_UNIXUNIX domain protocolsUNIX域协议unix(7)*
AF_PACKETLow level packet interface protocols底层数据包接口协议packet(7)*
AF_BLUETOOTHBluetooth protocols蓝牙协议bluetooth(7)*
AF_NETLINKLinux Kernel user interface device protocolsLinux 内核用户界面设备协议netlink(7)*
AF_LOCALLocal to host protocols本地协议unix(7)
AF_X25ITU-T X.25 / ISO-8208 protocol familyX.25协议x25(7)
AF_AX25Amateur radio AX.25 protocol业余无线电AX.25协议ax25(7)*
AF_ATMPVCAccess to raw ATM PVCsATM PVC协议atmarp(7)
AF_APPLETALKAppleTalkAppleTalk协议ddp(7)
AF_ECONETAcorn EconetAcorn Econet协议econet(7)
AF_IPXIPX - Novell protocolsIPX协议ipx(7)
AF_ROSEAmateur Radio X.25 PLP业余无线电X.25 PLP协议rose(7)
AF_NETROMAmateur radio NET/ROM protocol业余无线电NET/ROM协议netrom(7)
AF_SECURITYSecurity Attribute-based Access Control Kernel Extensions安全属性访问控制内核扩展security(7)

2.5 socket里面的type

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

对于网络编程,最常用的是SOCK_STREAM(TCP协议)和SOCK_DGRAM(UDP协议)两种socket类型,分别对应TCP和UDP协议。如果你有任何其他问题,请随时提问!

Socket TypeDescription
SOCK_STREAM提供面向连接的、可靠的数据传输服务。使用TCP协议。
SOCK_DGRAM提供无连接的、不可靠的数据传输服务。使用UDP协议。
SOCK_SEQPACKET提供面向连接的、可靠的数据传输服务。与SOCK_STREAM不同的是,保留了数据的边界(即数据报之间不会混淆)。
SOCK_RAW提供原始网络协议访问。需要应用程序自行构造协议头部。
SOCK_RDM提供面向连接的、可靠的数据传输服务,但是保留数据的边界。这个类型的socket基本上已经被废弃了。
SOCK_DCCP提供基于数据报的数据传输服务,使用DCCP协议。
SOCK_PACKET提供原始以太网数据包的访问,需要特权权限。已经过时。
SOCK_CLOEXEC在创建socket时设置close-on-exec标志位,使得socket在exec调用时自动关闭。
SOCK_NONBLOCK在创建socket时设置non-blocking标志位,使得socket的I/O操作变为非阻塞。

SOCK_PACKET已经被废弃了。在Linux 2.2版本以前,SOCK_PACKET是一种特殊的socket类型,可以用于访问网络驱动程序,但是需要特权权限。在Linux 2.2版本之后,SOCK_PACKET被替换为了SOCK_RAW,SOCK_RAW可以提供相同的功能,而且不需要特权权限。
在Linux 2.4版本之后,SOCK_PACKET被重新引入了,但这次它只是作为一种socket族别(socket family),而不是一种socket类型。也就是说,现在我们可以使用PF_PACKET来创建一个SOCK_PACKET socket了,而不再使用SOCK_PACKET socket类型。
请注意,PF_PACKET是一种特殊的socket族别,用于在数据链路层上发送和接收数据。它可以与SOCK_RAW结合使用,来构造和解析以太网帧、ARP报文等,从而实现更灵活的网络编程。

2.6 socket里面的protocol

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

当调用socket函数时,如果protocol参数设置为0,则会选择默认的协议。默认的协议通常是与给定的域和套接字类型最匹配的协议。
但是,有些域和套接字类型支持多种协议。在这种情况下,可以使用protocol参数来选择特定的协议。例如,在IPv4中,SOCK_STREAM套接字类型支持TCP和SCTP协议,SOCK_DGRAM套接字类型支持UDP和DCCP协议。如果我们要使用SCTP协议而不是TCP协议来创建一个SOCK_STREAM套接字,则可以将protocol参数设置为IPPROTO_SCTP。
需要注意的是,不同的操作系统可能支持不同的协议,因此要根据具体的环境来选择正确的协议。此外,还需要了解不同协议之间的性能和特性差异,以确保选择的协议适合应用程序的需求。
当调用socket函数时,protocol参数可以根据不同的domain和type组合来选择适合的协议。以下是一些常见的domain和type组合以及对应的protocol:

DomainTypeProtocol
AF_INETSOCK_STREAMIPPROTO_TCP (TCP协议)
AF_INETSOCK_DGRAMIPPROTO_UDP (UDP协议)
AF_INET6SOCK_STREAMIPPROTO_TCP (TCP协议)
AF_INET6SOCK_DGRAMIPPROTO_UDP (UDP协议)
AF_UNIXSOCK_STREAM0 (默认协议,通常是UNIX域套接字)
AF_UNIXSOCK_DGRAM0 (默认协议,通常是UNIX域套接字)

这只是一些常见的组合,实际上还有很多的组合。

2.7 Linux系统下的C语言socket函数返回值

在Linux系统下,C语言的套接字函数(如socket()、bind()、listen()等)的返回值类型通常是int型。这些函数的返回值表示函数执行的结果或错误代码。如果函数执行成功,则返回一个非负的套接字描述符,用于后续的套接字操作。如果函数执行失败,则返回-1,并且可以通过检查全局变量errno来获取具体的错误代码。
常见的套接字函数返回值为-1的错误代码包括:

  • EACCES:权限不足,无法创建套接字。
  • EAFNOSUPPORT:不支持指定的地址族。
  • EINVAL:无效的参数。
  • EMFILE:达到了进程打开的文件描述符数量的上限。
  • ENFILE:达到了系统打开的文件描述符数量的上限。
  • ENOBUFS/ENOMEM:内存不足,无法分配资源。
    需要根据套接字函数的返回值和具体的错误代码来判断函数是否执行成功,并根据错误情况采取适当的处理措施。

3.setsockopt()函数 来设置socket的属性

3.1 Linux系统下的C语言setsockopt函数原型

// Set socket options
// Parameters:
//   sockfd: socket file descriptor
//   level: protocol level of the option (e.g., SOL_SOCKET for socket-level options)
//   optname: the name of the option to be set
//   optval: pointer to the memory area where the option value is stored
//   optlen: the length of the option value in bytes
// Return value:
//   If successful, returns 0; otherwise, returns -1
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

3.2 Linux系统下的C语言setsockopt位于哪个头文件

#include <sys/socket.h>

3.3 Linux系统下的C语言setsockopt函数参数说明

setsockopt()函数是一个用于设置套接字选项的系统调用函数。它允许应用程序在已打开的套接字上设置各种选项,以控制套接字的行为。
参数说明:

  • sockfd:指定要设置选项的套接字描述符。
  • level:指定选项所在的协议层。常用的协议层包括SOL_SOCKET(通用套接字选项)、IPPROTO_TCP(TCP协议选项)和IPPROTO_IP(IP协议选项)等。
  • optname:指定要设置的选项名称。
  • optval:指向存储选项值的缓冲区。
  • optlen:指定选项值的大小。
    下面是一些常见的套接字选项和它们的使用示例:
  1. 设置套接字为可重用:
int optval = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) 
{
    perror("setsockopt failed");
    exit(EXIT_FAILURE);
}

这个示例中, SO_REUSEADDR 选项被设置为1,表示允许地址重用。这对于服务器程序在关闭后立即重新启动时很有用。

  1. 设置接收或发送超时时间:
struct timeval timeout;
timeout.tv_sec = 5; // 5秒
timeout.tv_usec = 0;
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) 
{
    perror("setsockopt failed");
    exit(EXIT_FAILURE);
}

在这个示例中, SO_RCVTIMEO 选项被设置为5秒,表示在接收数据时最多等待5秒钟。如果在指定时间内没有接收到数据, recv() 函数将返回超时错误。

  1. 设置套接字缓冲区大小:
int optval = 8192; // 8KB
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &optval, sizeof(optval)) < 0) 
{
    perror("setsockopt failed");
    exit(EXIT_FAILURE);
}

这个示例中, SO_RCVBUF 选项被设置为8KB,表示接收缓冲区的大小为8KB。

3.4 Linux系统下的C语言setsockopt函数返回值

setsockopt()函数的返回值是一个整数,表示函数执行的结果。如果函数执行成功,则返回值为0;如果函数执行失败,则返回值为-1,并且可以通过检查全局变量errno来获取具体的错误代码。常见的错误代码包括:

  • EBADF:无效的套接字描述符。
  • ENOTSOCK:指定的文件描述符不是套接字。
  • EINVAL:无效的选项名称或选项值。
  • EPERM:当前用户权限不足,无法设置该选项。
    需要根据返回值来判断函数是否执行成功,并根据具体的错误代码来处理错误情况。

4.bind()函数 用于绑定端口

4.1 Linux系统下的C语言bind函数原型

// Bind the socket to an address
// Parameters:
//   sockfd: socket file descriptor
//   addr: pointer to the address structure to bind to
//   addrlen: length of the address structure in bytes
// Return value:
//   If successful, returns 0; otherwise, returns -1
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

4.2 Linux系统下的C语言bind位于哪个头文件

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

4.3 Linux系统下的C语言bind函数参数说明

在 bind 函数中,有三个参数需要说明:

  1. sockfd :表示要绑定的套接字文件描述符。它是通过调用 socket 函数创建的套接字的文件描述符。
  2. addr :是一个指向 struct sockaddr 类型的指针,用于指定要绑定的 IP 地址和端口信息。具体的地址信息取决于所使用的协议族(如 IPv4 或 IPv6)以及地址结构体的类型(如 struct sockaddr_in 或 struct sockaddr_in6 )。
  3. addrlen :是一个 socklen_t 类型的参数,表示传递给 addr 参数的地址结构体的长度。
    通过这三个参数, bind 函数可以将指定的套接字与特定的 IP 地址和端口进行绑定。
    4.4Linux系统下的C语言bind函数返回值
    在 Linux 系统下,C 语言的 bind 函数返回一个整数值。它的返回值表示函数执行的结果,具体含义如下:
  • 如果绑定成功, bind 函数返回 0。
  • 如果出现错误, bind 函数返回 -1,并设置相应的错误码。你可以使用 perror 函数打印错误信息,或者使用 errno 变量获取错误码。
    需要注意的是,不同的错误码代表不同的错误情况。你可以参考相关的文档或使用 man 命令来查看特定的错误码所对应的含义。

5.listen()函数 用于监听连接

5.1 Linux系统下的C语言listen函数原型

// Set the socket to listen for incoming connections
// Parameters:
//   sockfd: socket file descriptor
//   backlog: maximum number of pending connections in the waiting queue
// Return value:
//   If successful, returns 0; otherwise, returns -1
int listen(int sockfd, int backlog);

5.2 Linux系统下的C语言listen位于哪个头文件

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

5.3 Linux系统下的C语言listen函数参数说明

listen 函数接受两个参数:

  • sockfd :表示要监听的套接字文件描述符。它是通过调用 socket 函数创建的套接字的文件描述符。
  • backlog :表示等待连接队列的最大长度。它指定了在调用 accept 函数之前,可以排队等待的连接请求数量。

5.4 Linux系统下的C语言listen函数返回值

listen 函数返回一个整数值,表示函数执行的结果。具体含义如下:

  • 如果监听成功, listen 函数返回 0。
  • 如果出现错误, listen 函数返回 -1,并设置相应的错误码。你可以使用 perror 函数打印错误信息,或者使用 errno 变量获取错误码。
    需要注意的是,调用 listen 函数之前,必须先调用 bind 函数将套接字与特定的 IP 地址和端口进行绑定。否则, listen 函数将会失败。

6.accept()函数 接受连接并处理请求

6.1 Linux系统下的C语言accept函数原型

// Accept a client connection request and create a new socket to handle the connection
// Parameters:
//   sockfd: socket file descriptor
//   addr: pointer to the structure that will hold the client address information
//   addrlen: pointer to the length of the structure in bytes
// Return value:
//   If successful, returns the new socket file descriptor; otherwise, returns -1
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

6.2 Linux系统下的C语言accept位于哪个头文件

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

6.3 Linux系统下的C语言accept函数参数说明

  • sockfd :表示要接受连接请求的套接字文件描述符。它是通过调用 socket 函数创建的套接字的文件描述符。
  • addr :是一个指向 struct sockaddr 类型的指针,用于存储连接的客户端的地址信息。
  • addrlen :是一个指向 socklen_t 类型的指针,用于指定 addr 参数所指向的地址结构体的长度,并在函数调用后更新为实际接受的地址结构体的长度。

6.4 Linux系统下的C语言accept函数返回值

  • 如果接受连接成功, accept 函数返回一个新的套接字文件描述符,用于与客户端进行通信。
  • 如果出现错误, accept 函数返回 -1,并设置相应的错误码。你可以使用 perror 函数打印错误信息,或者使用 errno 变量获取错误码。
    需要注意的是, accept 函数会阻塞程序的执行,直到有客户端连接请求到达,或者出现错误。在多线程或多进程的网络编程中,可以使用 accept 函数来接受客户端连接请求,并将处理客户端请求的任务交给其他线程或进程来处理。

有空随手记,未完待续—

2024-01-09

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值