Ubuntu Linux 24.04 C语言TCP/IP socket编程基础知识

socket起源于Unix,Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行读/写IO、打开、关闭。根据美国计算机历史博物馆的记载,Croker写道:“一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定。”

网络端口编号从 0 到 65535,其中 0 - 1023 是公认的端口号,就是已经被一些知名的软件给占用了,留给我们程序里面使用的是 1024 - 65535 端口。
socket通过绑定操作占领某个端口,接下来其他程序将不能使用此端口,一旦此端口收到数据,系统都会转发给该程序。

在TCP/IP网络协议中,通信的两个进程间相互作用的主要模式是客户/服务器(Client/Server, C/S)模式,即客户向服务器发出服务请求,服务器接收到请求后,提供相应的服务,其过程如下:


(1)服务器创建一个socket,绑定到指定端口。
(2)开始监听等待客户请求的到来。
(3)客户端创建一个socket,绑定到随意一个可用的端口,然后向服务器的socket发送请求。
(4)接收到客户socket的请求时,为了不妨碍继续监听其它客户请求的工作,为当前客户创建一个专属的连接socket来处理该客户的请求,读取客户发送来的数据,发送应答数据给客户,操作完毕以后结束与该客户的连接,于此同时,监听socket则仍可以继续监听其它客户的请求,形成多线程并发操作。

下面是实现上述过程的Linux socket库函数

创建socket

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

函数原型位于 /usr/include/x86_64-linux-gnu/sys/socket.h
Create a new socket of type in domain, using protocol. 

返回值
根据这三个参数建立一个socket,并将相应的资源分配给它,Returns a file descriptor for the new socket, or -1 for errors.
domain 
指定通信发生的区域
AF_INET: For communicating between processes on different hosts connected by IPV4
AF_INET6:for processes connected by IPV6
AF_LOCAL: defined in the POSIX standard for communication between processes on the same host. 
type 
指communication type
(1)SOCK_STREAM: TCP(reliable, connection-oriented) ,数据无差错、无重复发送、按发送顺序接收。内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制。文件传送协议(FTP)即使用此。
(2)SOCK_DGRAM:UDP(unreliable, connectionless),数据报以独立包形式被发送,不提供无错保证,数据可能丢失或重复,并且接收顺序混乱。网络文件系统(NFS)使用此。
(3)SOCK_RAW:该接口允许对较低层协议,如IP、ICMP直接访问,常用于检验新的协议实现或访问现有服务中配置的新设备。
The concept of "connections" apply to SOCK_STREAM/TCP type of sockets. Connection means a reliable "stream" of data such that there can be multiple such streams each having communication of its own. Think of this as a pipe which is not interfered by other data.
Other sockets like UDP , ICMP , ARP don't have a concept of "connection". These are non-connection based communication. Which means you keep sending or receiving packets from anybody.
protocol 
说明socket使用的特定协议,默认为0,This is the same number that appears on the protocol field in the IP header of a packet.
If protocol is zero, one is chosen automatically.

设置socket的属性

int setsockopt (int fd, int level, int optname, const void *optval, socklen_t optlen);

函数原型位于 /usr/include/x86_64-linux-gnu/sys/socket.h

Set socket FD's option OPTNAME at protocol level LEVEL to *OPTVAL (which is OPTLEN bytes long). This helps in manipulating options for the socket. This is completely optional.

常用功能有:

1. reuse of address and port. Prevents error such as: “address already in use”.

2. 设置接收和发送超时的时长。

返回值

Returns 0 on success, -1 for errors.
 

指定socket监听的地址和端口

int bind (int fd, CONST_SOCKADDR_ARG addr, socklen_t len);

函数原型位于 /usr/include/x86_64-linux-gnu/sys/socket.h

Give the socket FD the local address ADDR (which is LEN bytes long),包括本地地址和本地端口。

返回值

如果没有错误发生,bind()返回0,否则返回-1

fd

被指定的socket
addr

本地地址,包括ip和port,INADDR_ANY 表示监听所有IP地址。
len
指定addr的长度。

socket开始监听连接请求

int listen (int fd, int n);

函数原型位于 /usr/include/x86_64-linux-gnu/sys/socket.h

Prepare to accept connections on socket FD.   N connection requests will be queued before further requests are refused.

返回值
Returns 0 on success, -1 for errors.
fd

监听socket

n
请求连接队列的最大长度,用于限制排队请求的个数,目前允许的最大值为5。

If a connection request arrives when the queue is full, the client may receive an error with an indication of ECONNREFUSED.
 

socket发起连接

int connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len);

函数原型位于 /usr/include/x86_64-linux-gnu/sys/socket.h

Open a connection on socket FD to peer at ADDR (which LEN bytes long).
For connectionless socket types, just set the default address to send to and the only address from which to accept transmissions.

返回值
Return 0 on success, -1 for errors.

fd

发起连接的socket
addr

连接目标socket的地址,包括ip和port.
len

addr的长度.


等待和接收连接请求

int accept (int fd, __SOCKADDR_ARG addr, socklen_t *__restrict addr_len);

函数原型位于 /usr/include/x86_64-linux-gnu/sys/socket.h

Await a connection on socket FD. When a connection arrives, open a new socket to communicate with it,  set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting peer and *ADDR_LEN to the address's actual length.

It extracts the first connection request on the queue of pending connections for the listening socket, creates a new connected socket, and returns a new file descriptor referring to that socket. At this point, the connection is established between client and server, and they are ready to transfer data.

返回值

return the new socket's descriptor, or -1 for errors.
fd

监听socket。
addr

用来接收客户socket的地址, addr的确切格式由socket创建时建立的地址族决定。
len

addr的实际字节数
 

socket发送数据

ssize_t send (int fd, const void *buf, size_t n, int flags);

函数原型位于 /usr/include/x86_64-linux-gnu/sys/socket.h

返回值
如果没有错误发生,send()返回总共发送的字节数; 否则它返回-1

fd  发送数据的socket。
buf  数据缓冲区的指针

buf的字节数
flags  指定传输控制方式,如是否接收带外数据等。

socket接收数据

ssize_t recv (int fd, void *buf, size_t n, int flags);

函数原型位于 /usr/include/x86_64-linux-gnu/sys/socket.h

Read N bytes into BUF from socket FD.

返回值
Returns the number read or -1 for errors. 如果连接被关闭,返回0

fd  接收数据的socket。
buf  接收数据缓冲区的指针

接收数据的最大字节数
flags  指定传输控制方式,如是否接收带外数据等。


关闭socket

int close (int fd);

函数原型位于 /usr/include/unistd.h

Close the file descriptor FD

通讯的双方都可以关闭当前的连接。

 

设置socket接收和发送超时的时长

一个新创建的socket默认是阻塞的,默认的socket发送和接收的超时时长为0,表明永不超时,意味着recv/send会一直等待对方发送和接收数据,这显然是不行的,要设置socket发送和接收超时的时长。

struct timeval {__kernel_old_time_t	tv_sec;		/* seconds */__kernel_suseconds_t	tv_usec;	/* microseconds */
};

struct timeval的定义在 /usr/include/linux/time.h


1.  获取接收的超时值

socklen_t optlen = sizeof(struct timeval);
struct timeval tv;
getsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &optlen); 

2. 设置接收的超时值

socklen_t optlen = sizeof(struct timeval);
struct timeval tv; tv.tv_sec = 10; tv.tv_usec = 0; // 10秒后超时
setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, optlen);

检查getsockopt和setsockopt函数的返回值,0表示成功,-1表示失败。
设置发送超时与接收超时类似,只需将SO_RCVTIMEO改为SO_SNDTIMEO

socket常用的数据结构

// 定义于 /usr/include/linux/in.h/* Internet address. */
struct in_addr {__be32	s_addr; // long int format of IP address
};/* Structure describing an Internet (IP) socket address. */
struct sockaddr_in {__kernel_sa_family_t	sin_family;	/* Address family		*/__be16		sin_port;	        /* Port number			*/struct in_addr	sin_addr;	    /* Internet address		*//* Pad to size of `struct sockaddr'. */unsigned char		__pad[__SOCK_SIZE__ - sizeof(short int) - sizeof(unsigned short int) - sizeof(struct in_addr)];
};/* Structure describing a generic socket address.  */
struct sockaddr {__SOCKADDR_COMMON (sa_);	/* Common data: address family and length.  */char sa_data[14];		/* Address data.  */
};/* Description of data base entry for a single host.  */
struct hostent
{char *h_name;			/* Official name of host.  */char **h_aliases;		/* Alias list.  */int h_addrtype;		/* Host address type.  */int h_length;			/* Length of address.  */char **h_addr_list;		/* List of addresses from name server.  */
#ifdef __USE_MISC
# define	h_addr	h_addr_list[0] /* Address, for backward compatibility.*/
#endif
};

操作地址的函数

/* 定义于/usr/include/arpa/inet.hConvert Internet host address from numbers-and-dots notation in CPinto binary data in network byte order.  eg: in_addr.s_addr = inet_addr("74.125.235.20");*/
in_addr_t inet_addr (const char *cp);

本文参考资料

ubuntu linux 24.04
https://blog.csdn.net/qiuchangyong/article/details/82757819
https://www.binarytides.com/socket-programming-c-linux-tutorial/#google_vignette
https://www.geeksforgeeks.org/socket-programming-cc/
https://www.cnblogs.com/bandaoyu/p/16752853.html

以上如有错漏之处,敬请大家指正。我的联系方式:
微信:TobeBuda
Email/Paypal: jinmin.si@outlook.com
邀请您加入「社区资讯服务」创业微信群,共同探讨打造社区资讯服务的美好未来。

2024年6月16日

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/28184.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 部门项目任务分配(100分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 📎在线评测链接 部门项目任务分配(100分) 🌍 评测功能需要订阅专栏后私信联…

举例说明 如何通过SparkUI和日志定位任务莫名失败?

有一个Task OOM: 通过概览信息,发现Stage 10的Task 36失败了4次导致Job失败。概览信息中显示最后一次失败的退出代码(exit code)是143,意味着发生了内存溢出(OOM,即Out of Memory)。…

探索Edge

目录 1.概述 1.1.什么是浏览器 1.2.浏览器的作用 2.Edge 2.1.什么是Edge 2.2.诞生背景 2.3.历史版本 2.4.作用 2.5.优缺点 2.5.1.优点 2.5.2.缺点 3.对比 3.1.和360浏览器的对比 3.2.和谷歌浏览器(Chrome)的对比 4.未来展望 5.总结 1.概…

从“产品的RFM分析”看如何探索“职业方向”

我们在做产品分析时,经常会用到一种方法“产品的RFM分析”,它是一种客户细分和价值评估的常用方法,广泛应用于电子商务、零售和其他众多行业,它可以帮助企业和产品团队更好地理解用户行为,优化营销策略,提升…

Python基础教程(二十二):XML解析

💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 💝&#x1f49…

0 算法复杂度

算法复杂度 时间复杂度有关总结 一,常数时间的操作【基本操作】 常数时间——固定时间——O(1)——由实现细节决定 不会随着输入规模的变化而增加时间复杂度 1 基本操作解析 1.算数操作: ab a-b a*b a/b int a 32位 int b 32位11 178997…

Linux--MQTT(二)通信基本原理

一、MQTT 通信基本原理 MQTT 是一种基于 客户端 - 服务端 架构的消息传输协议,所以在 MQTT 协议通信中,有两个最为重要的角色,它们便是服务端 和 客户端 。 举例:若开发板向“芯片温度”这一主题发布消息,那么服务…

cocos开发的时候 wx.onShow在vscode里面显示红色

这个函数是在微信小游戏平台才会用到。 cocos识别不到wx这个变量。 可以改成下面的写法。 只要在变量前面加一个globalThis.就能识别这个变量了。也不报错了。 搞死强迫症了。orz 欢迎大家来玩我的微信小游戏。多多提意见啊。

欧阳修,仕途波澜中的文坛巨匠

欧阳修,字永叔,号醉翁、六一居士,生于北宋真宗景德四年(公元1007年),卒于北宋神宗熙宁五年(公元1072年),享年65岁。他是北宋时期著名的文学家、史学家,也是唐…

计算机缺失d3dcompiler_43.dll怎么办,介绍5种靠谱的解决方法

在电脑使用过程中,我们经常会遇到一些错误提示,其中之一就是“找不到d3dcompiler43.dll”的错误。那么,d3dcompiler43.dll到底是什么?为什么会出现丢失的情况?它对计算机有什么具体影响?如何解决这个问题&a…

数据库系统概念(第七周 第二堂)(E-R模型转关系模式)

前言 前一堂课我们深入研究了E-R模型的画法和要点,学习E-R模型肯定是为了给数据库表格设计提供帮助。数据库表格设计就是关系模式设计,数据库表就是关系模式的实例化。所以本堂课,我们来看E-R模型如何转为关系模式。 转化原则 转化步骤 转…

[Vulnhub]Solid-State POP3邮件服务(James)+rbash逃逸

信息收集&SSH Server IP addressPorts Open192.168.8.100TCP:22,25,80,110,119,4555 Nmap 扫描: $ nmap -p- 192.168.8.100 --min-rate 1000 -sC -sV 结果: Host is up (0.00061s latency). Not shown: 65529 closed tcp ports (conn-refused) PORT STATE SERVICE…

phpStudy安装sqli-labs

phpStudy安装sqli-labs git地址:https://github.com/Audi-1/sqli-labs 点击管理–>根目录 将git下载的sqli-labs文件放进去并解压 进入sql-connections修改 修改db-creds.inc文件为自己数据库的账号密码 更改php版本为5.*,因为这个程序只能在php 5.…

[Golang] go-kit 介绍和使用 (微服务实现工具)

文章目录 1.go-kit 介绍1.1 go-kit 三层结构 2.go-kit 实例 1.go-kit 介绍 go-kit是一个分布式的开发工具集,在大型的组织(业务)中可以用来构建微服务,其解决了分布式系统中大多数常见问题,因此,使用者可以…

Paragon NTFS for Mac 15软件下载-详细安装教程视频

​Paragon NTFS for Mac是Mac平台上一款非常优秀的读写工具,可以在Mac OS X中完全读写、修改、访问NTFS硬盘、U盘等外接设备的文件。这款软件最大的亮点简书可以让我们读写 NTFS 分区,因为在Mac OS X 系统上,默认状态下我们只能读取NTFS 分区…

Spring-kafka消费者消费的一些问题

前言 Spring Kafka 无缝集成了 Spring Boot、Spring Framework 及其生态系统中的其他项目,如 Spring Cloud。通过与 Spring Boot 的自动配置结合,开发者可以快速启动和配置 Kafka 相关的功能。无需编写大量样板代码即可实现 Kafka 的生产和消费功能&…

【源码】16国语言交易所源码/币币交易+期权交易+秒合约交易+永续合约+交割合约+新币申购+投资理财/手机端uniapp纯源码+PC纯源码+后端PHP

测试环境:Linux系统CentOS7.6、宝塔面板、Nginx、PHP7.3、MySQL5.6,根目录public,伪静态laravel5,开启ssl证书 语言:16种,看图 这套带前端uniapp纯源码,手机端和pc端都有纯源码,后…

list集合自定义排序

一、基本类型排序 1.list中只有数字或字符串 //升序排序 List<T> ,T为数字或字符串 Collections.sort(list); //降序排序 Collections.sort(list,Collections.reverseOrder());2.list中为对象 基于jdk.18 import lombok.Data;Data public class User {private int i…

Linux下Shell脚本基础知识

主要参考视频&#xff1a; 这可能是B站讲的最好的Linux Shell脚本教程&#xff0c;3h打通Linux-shell全套教程&#xff0c;从入门到精通完整版_哔哩哔哩_bilibili 主要参考文档&#xff1a; Shell 教程 | 菜鸟教程 (runoob.com) Bash Shell教程 (yiibai.com) 先用视频入门&…

基于springboot实现火锅店管理系统项目【项目源码+论文说明】

基于springboot实现火锅店管理系统演示 摘要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装火锅店管理系统软件来…