Linux----网络通信

目录

1.为什么要用网络通信?

2.IP和端口

3.网络传输中的2个对象:server和client 

 4.两种传输方式:TCP/UDP

(1).TCP和UDP原理上的区别

(2). UDP 协议存在的意义

(3). TCP/UDP 网络通信大概交互图

 5.网络编程主要函数介绍

(1).socket 函数(未涉及三要素)

(2).bind 函数---绑定IP和端口

(3).listen 函数---监听

(4).accept 函数

(5).connect 函数

(6). send 函数

(7).recv 函数

(8).recvfrom 函数

(9).sendto 函数


1.为什么要用网络通信?

        在客户端-服务器架构模型中,客户端向服务器发送请求,服务器处理请求并返回结果。这种架构适用于Web服务、数据库查询等多种应用场景,而printf只能用于本地输出,无法满足跨网络的数据交换需求。 

2.IP和端口

        所有的数据传输,都有三个要素:源、目的、长度

        如何表示或者目的呢?

  •  笔记本上两个浏览器访问同一个网站,浏览器发出的数据里,源IP、服务器IP、目的端口都相同。但是他们的源端口不一样,服务器根据源端口来区分一个IP下的两个连接。
  •  笔记本上两个软件,SSH Client和浏览器访问同一个网站,SSH Client想使用SSH服务,浏览器想使用http服务,这两个程序要访问的服务器时同一个,IP相同。但是端口不一样http服务是80端口,SSH服务是22端口

所以,在网络传输中需要使用“ IP 和端口”来表示源或目的。

3.网络传输中的2个对象:server和client
 

     在日常访问的浏览器中涉及2个对象:网站服务器,浏览器。网站服务器平时处于等待,浏览器主动发起数据请求。网站服务器、浏览器可以抽象成 2 个软件的概念: server 程序、 client 程ge序。

图 3.1 网络客户端和服务器
 

 4.两种传输方式:TCP/UDP

        在学习计算机网络的数据中,网络协议被分为5层。如图4.1所示:

 图4.1网络协议层

         此处只简单介绍运输层,对于其他4层不做介绍。

        运输层:负责向两个主机中进程之间的通信提供服务。

        运输层主要使用以下两种协议:

  • 传输控制协议TCP(Transmission Control Protocol):面向连接的,数据传输的单位是报文段,提供可靠的交付。如命令传输。
  • 用户数据包协议UDP(User Datagram Protocol):无连接的,数据传输的单位是用户数据报,不保证提供可靠交付只能提供“尽最大努力交付”

  我们需要使用“运输层”编写应用程序,我们的应用程序位于“应用层”。使用“运输层”时,可以选择 TCP 协议,也可以选择 UDP 协议。

(1).TCP和UDP原理上的区别

  •       TCP 向它的应用程序提供了面向连接的服务。这种服务有 2 个特点:可靠传输、流量控制(即发送方/接收方速率匹配)。它包括了应用层报文划分为短报文,并提供拥塞控制机制。
  •       UDP 协议向它的应用程序提供无连接服务。它没有可靠性,没有流量控制,也没有拥塞控制。

(2). UDP 协议存在的意义


      既然 TCP 提供了可靠数据传输服务,而 UDP 不能提供,但是有许多应用更适合用 UDP,例如,视频通话时,使用 UDP,偶尔的丢包、偶尔的花屏时可以忍受的;如果使用 TCP,每个数据包都要确保可靠传输,当它出错时就重传,这会导致后续的数据包被阻滞,视频效果反而不好。

  UDP 特点:

  • 发送数据控制的更为精细。采用 UDP 时只要应用进程将数据传递给 UDP, UDP 就会立即将其传递给网络层。而 TCP 有重传机制,不管可靠交付需要多长时间。但是实时应用通常不希望过分的延迟报文段的传送,且能容忍一部分数据丢失。
  • 无需建立连接,不会引入建立连接时的延迟。
  • 无连接状态,能支持更多的活跃客户。
  • 分组首部开销较小。
     

(3). TCP/UDP 网络通信大概交互图

4.1 面向连接的 TCP 流模式 

图4.2 UDP 用户数据包模式

 5.网络编程主要函数介绍

        bind,listen 和 accept 是服务器端用的函数。

(1).socket 函数(未涉及三要素)

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

 作用:用于创建一个套接字(socket),该套接字可以用于后续的网络通信。

参数domain(地址族):常见的值包括:

  • AF_INET:IPv4 地址族
  • AF_INET6:IPv6 地址族
  • AF_UNIX:本地通信(Unix 域套接字)

参数type(套接字类型):常见的值包括:

  • SOCK_STREAM:面向连接的流式套接字,通常用于 TCP 协议
  • SOCK_DGRAM:无连接的数据报套接字,通常用于 UDP 协议
  • SOCK_RAW:原始套接字,用于底层网络协议开发

参数protocol(协议):由于指定了 type,所以这个地方一般只要用 0 来代替就可以了。

返回值:此函数执行成功时返回文件描述符,失败时返回-1,看 errno 可知道出错的详细情况。

(2).bind 函数---绑定IP和端口

int bind(int sockfd, struct sockaddr *my_addr, int addrlen);

 作用:用于将地址绑定到一个套接字。

参数sockfd (套接字描述符):这是由 socket 函数创建的套接字描述符。

参数my_addr(地址结构指针)

  • 指向一个包含地址信息的结构体的指针。对于 IPv4,通常使用 struct sockaddr_in 结构体;对于 IPv6,通常使用 struct sockaddr_in6 结构体。

sockaddr_in 的定义:

struct sockaddr_in{
unsigned short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
}
如果使用 Internet 所以 sin_family 一般为 AF_INET。
⚫ sin_addr 设置为 INADDR_ANY 表示可以和任何的主机通信。
⚫ sin_port 是要监听的端口号。
⚫ bind 将本地的端口同 socket 返回的文件描述符捆绑在一起.成功是返回 0,
失败的情况和 socket 一样。

参数addrlen (地址结构长度):指定地址结构体的长度。

返回值:成功时返回 0。失败时返回 -1,并设置 errno 变量以指示错误原因。

(3).listen 函数---监听

int listen(int sockfd,int backlog);

作用: 宣告服务器可以接受连接请求,将 bind 的文件描述符变为监听套接字。

参数sockfd : bind 后的文件描述符。

参数backlog: 设置请求排队的最大长度。当有多个客户端程序和服务端相连时,使用这个表示可以介绍的排队长度。
返回值:返回的情况和 bind 一样。

(4).accept 函数

int accept(int sockfd, struct sockaddr *addr,int *addrlen);

作用: 服务器使用此函数获得连接请求,并且建立连接。

参数sockfd:listen 后的文件描述符。

参数addr和addrlen:用来给客户端的程序填写的,服务器端只要传递指针就可以了

tips:accept 调用时,服务器端的程序会一直阻塞到有一个客户程序发出了连接。accept 成功时返回最后的服务器端的文件描述符,这个时候服务器端可以向该描述符写信息了,失败时返回-1 。

(5).connect 函数

int connect(int sockfd, struct sockaddr * serv_addr,int addrlen);

作用:建立一个连接,在 connect 中所指定的地址是想与之通信的服务器的地址。

参数sockfd:socket 函数返回的文件描述符。
参数serv_addr:储存了服务器端的连接信息,其中 sin_add 是服务端的地址。

参数addrlen:serv_addr 的长度

返回值:成功时返回 0,失败时返回-1。

(6). send 函数

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

 作用:客户端和服务器都用send函数向另一端发送数据。

参数sockfd: 指定发送端套接字描述符;
参数buf: 指明一个存放应用程序要发送数据的缓冲区;
参数len: 指明实际要发送的数据的字节数;
参数flags: 一般置 0。

返回值:回实际发送的字节数。失败返回 -1,并设置 errno 变量以指示错误原因。

(7).recv 函数

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

 作用:客户或者服务器应用程序都用 recv 函数从 TCP 连接的另一端接收数据。

参数sockfd: 指定接收端套接字描述符;
参数buf: 指明一个缓冲区,该缓冲区用来存放 recv 函数接收到的数据;
参数len: 指明 buf 的长度;
参数flags :一般置 0。

返回值:回实际发送的字节数。失败返回 -1,并设置 errno 变量以指示错误原因。

(8).recvfrom 函数

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
    struct sockaddr *src_addr, socklen_t *addrlen);

 参数 recvfrom :通常用于无连接套接字,因为此函数可以获得发送者的地址。
 参数 src_addr: 是一个 struct sockaddr 类型的变量,该变量保存源机的 IP 地址及端口号。
 参数 addrlen: 常置为 sizeof ( struct sockaddr)。

返回值:回实际发送的字节数。失败返回 -1,并设置 errno 变量以指示错误原因。

(9).sendto 函数

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
        const struct sockaddr *dest_addr, socklen_t addrlen);

sendto 和 send 相似,区别在于 sendto 允许在无连接的套接字上指定一个
目标地址。
参数dest_addr: 表示目地机的 IP 地址和端口号信息,
参数addrlen: 常常被赋值为 sizeof ( struct sockaddr)。
返回值:回实际发送的字节数。失败返回 -1,并设置 errno 变量以指示错误原因。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值