146 Linux 网络编程2 ,Socket编程,如何创建Linux 服务器 和linux 客户端

IP+port 就是一个程序在网络上的身份证号码。

这意味着我们需要如果写一个服务器,至少需要将这台服务器的ip 和 端口号写到程序里面。

实际上更细化的说:应该是将这三都写进程序里面 : IP类型(IPV4或者IPV6),IP地址(192.168.39.78),端口号(900)

套接字概念

Socket本身有“插座”的意思,在Linux环境下,用于表示进程间网络通信的特殊文件类型。本质为内核借助缓冲区形成的伪文件。

既然是文件,那么理所当然的,我们可以使用文件描述符引用套接字。与管道类似的,Linux系统将其封装成文件的目的是为了统一接口,使得读写套接字和读写文件的操作一致。区别是管道主要应用于本地进程间通信,而套接字多应用于网络进程间数据的传递。

套接字的内核实现较为复杂,不宜在学习初期深入学习。

在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程。“IP地址+端口号”就对应一个socket。欲建立连接的两个进程各自有一个socket来标识,那么这两个socket组成的socket pair就唯一标识一个连接。因此可以用Socket来描述网络连接的一对一关系。

套接字通信原理如下图所示:

在网络通信中,套接字一定是成对出现的。

预备知识

网络字节序

我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分,磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分。网络数据流同样有大端小端之分,那么如何定义网络数据流的地址呢?发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出,接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存,因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址。

TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。例如上一节的UDP段格式,地址0-1是16位的源端口号,如果这个端口号是1000(0x3e8),则地址0是0x03,地址1是0xe8,也就是先发0x03,再发0xe8,这16位在发送主机的缓冲区中也应该是低地址存0x03,高地址存0xe8。但是,如果发送主机是小端字节序的,这16位被解释成0xe803,而不是1000。因此,发送主机把1000填到发送缓冲区之前需要做字节序的转换。同样地,接收主机如果是小端字节序的,接到16位的源端口号也要做字节序的转换。如果主机是大端字节序的,发送和接收都不需要做转换。同理,32位的IP地址也要考虑网络字节序和主机字节序的问题。

为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t netlong);

uint16_t ntohs(uint16_t netshort);

h表示host,n表示network,l表示32位长整数,s表示16位短整数。

如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回,如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。

IP地址转换函数

早期:

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

int inet_aton(const char *cp, struct in_addr *inp);

in_addr_t inet_addr(const char *cp);

char *inet_ntoa(struct in_addr in);

只能处理IPv4的ip地址

不可重入函数

注意参数是struct in_addr

现在:

#include <arpa/inet.h>

int inet_pton(int af, const char *src, void *dst);

const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

支持IPv4和IPv6

可重入函数

其中inet_pton和inet_ntop不仅可以转换IPv4的in_addr,还可以转换IPv6的in6_addr。

因此函数接口是void *addrptr。

sockaddr数据结构

strcut sockaddr 很多网络编程函数诞生早于IPv4协议,那时候都使用的是sockaddr结构体,为了向前兼容,现在sockaddr退化成了(void *)的作用,传递一个地址给函数,至于这个函数是sockaddr_in还是sockaddr_in6,由地址族确定,然后函数内部再强制类型转化为所需的地址类型。

可参看 man 7 ip

网络套接字函数

socket模型创建流程图

socket函数

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
domain:
	AF_INET 这是大多数用来产生socket的协议,使用TCP或UDP来传输,用IPv4的地址
	AF_INET6 与上面类似,不过是来用IPv6的地址
	AF_UNIX 本地协议,使用在Unix和Linux系统上,一般都是当客户端和服务器在同一台及其上的时候使用
type:
	SOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。
	SOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。
	SOCK_SEQPACKET该协议是双线路的、可靠的连接,发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取。
	SOCK_RAW socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议)
	SOCK_RDM 这个类型是很少使用的,在大部分的操作系统上没有实现,它是提供给数据链路层使用,不保证数据包的顺序
protocol:
	传0 表示使用默认协议。
返回值:
	成功:返回指向新创建的socket的文件描述符,失败:返回-1,设置errno

socket()打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符,应用程序可以像读写文件一样用read/write在网络上收发数据,如果socket()调用出错则返回-1。

对于IPv4,domain参数指定为AF_INET。

对于TCP协议,type参数指定为SOCK_STREAM,表示面向流的传输协议。

如果是UDP协议,则type参数指定为SOCK_DGRAM,表示面向数据报的传输协议。

protocol参数的介绍从略,指定为0即可。

bind函数

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd:
	socket文件描述符
addr:
	构造出IP地址加端口号
addrlen:
	sizeof(addr)长度
返回值:
	成功返回0,失败返回-1, 设置errno

服务器程序所监听的网络地址和端口号通常是固定不变的,客户端程序得知服务器程序的地址和端口号后就可以向服务器发起连接,因此服务器需要调用bind绑定一个固定的网络地址和端口号。

bind()的作用是将参数sockfd和addr绑定在一起,使sockfd这个用于网络通讯的文件描述符监听addr所描述的地址和端口号。前面讲过,struct sockaddr *是一个通用指针类型,addr参数实际上可以接受多种协议的sockaddr结构体,而它们的长度各不相同,所以需要第三个参数addrlen指定结构体的长度。如:

struct sockaddr_in servaddr;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(6666);

首先将整个结构体清零,然后设置地址类型为AF_INET,网络地址为INADDR_ANY,这个宏表示本地的任意IP地址,因为服务器可能有多个网卡,每个网卡也可能绑定多个IP地址,这样设置可以在所有的IP地址上监听,直到与某个客户端建立了连接时才确定下来到底用哪个IP地址,端口号为6666。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

5分钟教你激活喀秋莎Camtasia2023中文破解Crack下载附安装教程

Camtasia2023又称喀秋莎2023&#xff0c;集屏幕录制和视频剪辑功能于一体的软件&#xff0c;提供屏幕录制、区域录制、摄像头录制等多种录制方式&#xff0c;Camtasia2023版本带来了新的动态背景库、霓虹光标图像、录制语音旁白等多种新功能&#xff0c;适用于游戏录制、课程录…

Jupyter Notebook出错提示An error occurred while retrieving package information解决办法

出错日志信息&#xff1a; To access the notebook, open this file in a browser:file:///C:/Users/colda/AppData/Roaming/jupyter/runtime/nbserver-14564-open.htmlOr copy and paste one of these URLs:http://localhost:8888/?token3c0113e5da07c0b8b8c9de74ffb453c5047…

Python下有关CV的一些算法和函数

目录&#xff1a; 1. HoughCircles二级目录三级目录 1. HoughCircles 霍夫圆检测 二级目录 三级目录

【Docker】一文趣谈Docker

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 …

数学与计算机(2)- 线性代数

原文&#xff1a;https://blog.iyatt.com/?p13044 1 矩阵 NumPy 中 array 和 matrix 都可以用于储存矩阵&#xff0c;后者是前者的子类&#xff0c;array 可以表示任意维度&#xff0c;matrix 只能是二维&#xff0c;相当于矩阵专用&#xff0c;在一些矩阵的运算操作上较为直…

Python语法糖

N u m P y NumPy NumPy的 n d i t e r nditer nditer nditer 是 NumPy 提供的一种多维迭代器&#xff0c;用于对多维数组进行迭代操作。它可以替代传统的嵌套循环&#xff0c;在处理多维数组时更加方便和高效。 迭代器可以按照不同的顺序遍历数组的元素&#xff0c;也可以控制…

MyFileServer

靶场下载地址 https://download.vulnhub.com/myfileserver/My_file_server_1.ova 信息收集 # nmap -sn 192.168.56.0/24 -oN live.nmap Starting Nmap 7.94 ( https://nmap.org ) at 2024-02-24 22:07 CST Nmap scan report for 192.168.56.2 (192.168.56.2) Host is up (0.…

字节跳动后端工程师实习生笔试题-c++

字节跳动后端工程师实习生笔试题链接 笔试题 1. 最大映射2. 木棒拼图3. 魔法权值4. 或与加 1. 最大映射 有 n 个字符串&#xff0c;每个字符串都是由 A-J 的大写字符构成。现在你将每个字符映射为一个 0-9 的数字&#xff0c;不同字符映射为不同的数字。这样每个字符串就可以看…

1990-2022年各省全要素生产率数据(仅结果)

1990-2022年各省全要素生产率数据&#xff08;仅结果&#xff09; 1、时间&#xff1a;1990-2022年 2、指标&#xff1a;地区、年份、OLS、FE、RE、DGMM、SGMM、SFA1、SFA2、SFA3、SFA3D、TFE、非参数法 3、范围&#xff1a;31省 4、计算说明&#xff1a; 产出指标&#x…

了解 HTTP 请求的五个关键要素

一个成功的 HTTP 请求不仅仅意味着简单地发送一个请求并接收到响应。事实上&#xff0c;每个 HTTP 请求都需要具备五大要点&#xff0c;这些要点确保了请求的正确性、可靠性和用户体验。在本文中&#xff0c;我们将探讨这五大要点&#xff0c;即发送适当的请求、显示加载状态、…

明日周刊-第2期

三月份的第3周&#xff0c;第2期如期而至。大家希望看到什么内容也可以在评论区互动。 第2期-明日周刊 1. 一周热点1.1 国内新闻1.2 国际新闻1.3 科技新闻1.4 社会新闻 2. 资源分享3. 言论4. 歌曲推荐 1. 一周热点 1.1 国内新闻 中国成功发射遥感三十五号05组卫星 本周&#…

微信小程序-微信支付

微信支付介绍 梳理一下流程&#xff1a; 1、用户点击下单&#xff0c;小程序向商户系统&#xff08;我们的服务器&#xff09;发起请求&#xff0c;服务器生成一个唯一订单号给小程序。 2、小程序向服务器发起微信支付请求&#xff0c;服务器调用微信下单接口&#xff0c;微信…

从排序算法的艺术看C语言qsort函数的魅力:一场数据的时空穿越

欢迎来到白刘的领域 Miracle_86.-CSDN博客 系列专栏 C语言知识 先赞后看&#xff0c;已成习惯 创作不易&#xff0c;多多支持&#xff01; 目录 一 、回调函数 二、qsort函数 1.qsort函数排序整型数据 2.qsort函数排序结构数据 一 、回调函数 何为回调函数&#xff1…

STL容器之list类

文章目录 STL容器之list类1、list的介绍2、list的使用2.1、list的常见构造2.2、list的iterator的使用2.3、list空间增长问题2.4、list的增删查改2.5、list迭代器失效问题 3、list的模拟实现&#xff08;含反向迭代器&#xff09; STL容器之list类 1、list的介绍 list是序列容器…

五、保持长期高效的七个法则(二)Rules for Staying Productive Long-Term(1)

For instance - lets say youre a writer.You have a bunch of tasks on your plate for the day, but all of a sudden you get a really good idea for an essay. You should probably start writing now or youll lose your train of thought.What should you do? 举例来说…

rust引用本地crate

我们可以动态引用crate&#xff0c;build时从crate.io下载&#xff0c;但可能因无法下载导致build失败。首次正常引用三方crate&#xff0c;build时自动下载的crate源码&#xff0c;我们将其拷贝到固定目录中&#xff1b; build后可在RustRover中按住Ctrl键&#xff0c;在crat…

【Linux】环境基础开发工具使用

目录 Linux软件管理器 yum 1.什么是软件包 2.查看软件包 3安装与卸载 vim-Linux编辑器 1.vim基础概念 2.vim的基础操作 命令模式基本操作 底层模式基本操作 3、其它模式 Linux编译器 gcc/g 1.如何进行编译 2.编译的四个过程 预处理(-E) 编译(-S) 汇编(-c) 链接…

代码算法训练营day10 | 232.用栈实现队列、225. 用队列实现栈

day10: 232.用栈实现队列225. 用队列实现栈 232.用栈实现队列 题目链接 状态&#xff1a; 文档&#xff1a;programmercarl.com 思路&#xff1a; 用栈实现队列。要先明白两者的区别。 栈&#xff1a;单开门&#xff0c;先进后出&#xff0c;只有一端能进出。 队列&#xff1a;…

【论文笔记合集】LSTNet之循环跳跃连接

本文作者&#xff1a; slience_me LSTNet 循环跳跃连接 文章仅作为个人笔记 论文链接 文章原文 LSTNet [25] introduces convolutional neural networks (CNNs) with recurrent-skip connections to capture the short-term and long-term temporal patterns. LSTNet [25]引入…

1、鸿蒙学习-为应用/服务进行签名

针对应用/服务的签名&#xff0c;DevEco Studio为开发者提供了自动签名方案&#xff0c;帮助开发者高效进行调试。也可选择手动方式对应用/服务进行签名&#xff0c;如果使用了需要ACL的权限&#xff0c;需采用手动方式进行签名。 自动签名 说明 使用自动签名前&#xff0c;请…