Linux应用编程---13.网络编程

news2024/11/27 3:42:57

Linux应用编程—13.网络编程

​ 网络编程要熟悉一些计算机网络有关的名词,可以先做了解,后续实际开发在深入研究,自上而下学习。与本次Linux应用编程有关的就是TCP与UDP协议。简明概念如下图1所示。

在这里插入图片描述

图1 计算机网络体系结构

​ 前面学习的进程间通讯的方法有:管道、共享内存、消息队列。进程间同步的方法有:信号量、互斥锁。socket也是一种进程间进行数据交互的方法,用于网络连接的不同主机上的应用层程序进行数据交互。

13.1 服务器与客户端数据交互过程

在这里插入图片描述

图2 服务器与客户端数据交互过程

​ socket()函数系统调用创建一个新的socket(),使用时需要包含头文件sys/socket.h,函数原型为:int socket(int domain, int type, int protocol);函数成功时返回一个新建的socket的文件描述符。参数1domain:有3个可选项,确定了socket的通讯范围,如同一个主机上的应用程序之间还是位于使用一个网络连接起来的不同主机上的应用程序之间。一般可选参数如下:

Domain执行的通讯应用程序之间的通讯地址格式地址结构
AF_UNIX内核中同一主机路径名sockaddr_un
AF_INETIPv4通过IPv4连接起来的主机32位IPv4地址 + 16位端口号sockaddr_in
AF_INET6IPv6通过IPv6连接起来的主机128位IPv6地址 + 16位端口号sockaddr_in6
表1 socket domain

​ 参数2 type:socket有两种,流和数据报。它们区别如下表2所示:

属性socket类型
数据报
可靠地递送?
消息边界保留?
面向连接?
表2 socket类型及其属性

​ 其实根据这里地特点,可以联系到TCP与UDP的特点。其实,数据报socket使用了UDP协议,流socket使用了TCP协议。专业术语“UDP socket”和“TCP socket”。

​ 参数3protocol:一般使用默认值0即可。

​ 函数bind()作用是将一个socket绑定到一个地址上,函数原型位:int bind(int sockfd, const struct *addr, socklen_t addrlen);调用需要包含头文件sys/socket.h。参数1:sockfd是上一个socket()返回的文件描述符;参数0:addr是一个指针,指向了一个指定该socket绑定到的地址的结构,传入这个参数的结构的类型取决于socket domain。参数3:addelen参数指定了地址结构的大小。

​ 根据上面的domain的3种类型,地址格式各不相同。保存这个地址需要定义不同的结构体才行,但为了这个结构体类型能够接受任意数据的地址结构,socket API定义了一个通用的地址结构struct skcketaddr。用来将不同的domain特定的地址结构转换为单个类型供socket系统调用的各个参数使用。socketaddr结构体通常定义如下所示:

struct sockaddr
{
    sa_family_t sa_family;			// AF_ * constant, sa_family_t 整数类型
    char		sa_data[14];		// socket addr, size varies according to socket domain.
};

​ 实际使用

​ 函数listen()将文件描述符sockfd引用的流socket标记为被动,这个socket后面会被用来接受来自其它(主动的)socket的连接。函数原型为int listen(int sockfd, int backlog);使用时需要包含头文件sys/socket.h。参数1:sockfd是上一个socket()返回的文件描述符;参数2:backlog表示允许限制这种未决连接的数量,在这个数量之内连接请求会立即成功。什么是未决连接,如下图3所示:

image-20221220165726277

图3 未决连接(图片来之Linux_UNIX系统编程手册(下)P951)

​ 函数accept()在文件描述符sockfd引用的监听流socket上接受一个接入连接。如果在调用accept()时不存在未决的连接,那么调用就会阻塞直到有连接请求为止。函数原型为int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);调用时需要包含头文件sys/socket.h。函数accept()调用返回结果是已连接的socket的文件描述符。函数accept()会创建一个新的socket,这个新的socket会与执行connect()的对等socket()进行连接。addr参数指向一个用来返回socket地址的结构,该参数类型取决于socket domain。参数addrlen指向一个整数,调用前需要将这个整数初始化为addr指向的缓冲区的大小。内核才知道有多少空间用于返回socket地址。当accept()返回后,这个addrlen会被设置成实际被复制进缓冲区中的数据的字节数。

​ 函数connect()用于连接到对等socket,将文件描述符sockfd引用的主动socket连接到地址通过addr和addrlen指定的监听socket上。函数原型为int connect(int sockfd, const struct sockaddr * addr, socklen_t addrlen);调用需要包含头文件sys/socket.h。参数1:文件描述符sockfd是主动socket将它连接到地址通过addr和addrlen指定的监听socket上。剩余参数addr与addrlen参数指定方式与bind()函数相同。

​ 函数close()用来终止一个流socket。

13.2 编写一个TCP服务器

在这里插入图片描述

图4 TCP客户端、服务器通讯流程图

​ 服务器代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define FAILE -1
#define SUCCESS 0
#define PORT 8800
#define SIZE 100

int main(void)
{
        int ret = 0;
        int sock_fd, client_sockfd = 0;
        int addr_len = sizeof(struct sockaddr);
        char str[SIZE] = "Welcom to connect Server.";
        struct sockaddr_in my_sockaddr, client_addr;

        my_sockaddr.sin_family = AF_INET;
        my_sockaddr.sin_port = htons(PORT);			// htons()将整数转为网络字节序
        my_sockaddr.sin_addr.s_addr = INADDR_ANY;

        sock_fd = socket(AF_INET, SOCK_STREAM, 0);

        if(sock_fd == FAILE)
                perror("socket.");

        ret = bind(sock_fd, (struct sockaddr *)&my_sockaddr, sizeof(struct sockaddr));
        if(ret == FAILE)
                perror("bind.");

        ret = listen(sock_fd, 10);

        if(ret == FAILE)
                perror("listen.");

        while(1)
        {
                printf("Server is waiting for client to connect:\n");
                client_sockfd = accept(sock_fd, (struct sockaddr *)&client_addr, &addr_len);
                printf("Client address = %s\n", inet_ntoa(client_addr.sin_addr));			// inet_ntoa()将网络地址转换成“.”点隔的字符串格式
                send(client_sockfd, str, SIZE, 0);

                printf("Disconnect the client request.\n");

                close(client_sockfd);			// 关闭主动
        } 

        close(sock_fd);

        return 0;
}

​ 指定编译为SERVER可执行性文件。

​ 运行结果:

image-20221220212725978

图5 运行结果

​ 打印字符串,代码阻塞到accept()函数,等待有客户端连接。

​ 客户端运行时,通过main()函数传参传入IP地址。然后连接服务器,连接到后,会收到服务器发送的字符串,”Welcom to connect Server.“。打印字符串,并且关闭sock_fd。

​ 客户端代码:

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define FAILE -1
#define SUCCESS 0
#define PORT 8800
#define SIZE 100

int main(int argc, char * argv[])
{
        int ret = 0;
        int sock_fd = 0;
        struct sockaddr_in server_addr;
        char buff[SIZE];

        if(argc < 2)
        {
                printf("Usage: ./client [server IP address.\n]");
        }

        sock_fd = socket(AF_INET, SOCK_STREAM, 0);

        if(sock_fd == FAILE)
                perror("socket.");

        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(PORT);
        server_addr.sin_addr.s_addr = inet_addr(argv[1]);

        ret = connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
        if(ret == FAILE)
                perror("connext.");

        recv(sock_fd, buff, SIZE, 0);

        printf("Client receive from server: %s\n", buff);

        close(sock_fd);

        return 0;
}

​ 指定编译为CLIENT可执行性文件。

​ 运行代码,./CLIENT 192.168.20.129,这里的ip是虚拟机的ip地址,通过ifconfig查询。

​ 运行结果:

image-20221220214347136

图6 运行结果

在这里插入图片描述

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

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

相关文章

数控机床各种加工模式以及英文简写

AUTO&#xff08;自动模式&#xff09; 机床自动运行加工程序&#xff0c;对零件进行加工。前提是所编的程序经过试验后是可行的&#xff0c;而且是加工出来的件经过检验后是合格的&#xff0c;才可以使用该程序。 EDIT&#xff08;编辑模式&#xff09; 在此模式下&#xff…

Spring Boot集成第三方登录之微博登录

准备工作 微博开放平台&#xff1a;https://open.weibo.com/ 网站接入 登陆微博开放平台&#xff0c;进入微连接&#xff0c;选择网站接入 点击立即接入 开发者信息认证 填写开发者信息与身份认证信息 创建应用 开发者信息认证通过后即可创建应用。 应用创建成功后会得到app …

哪种台灯质量好又实惠?性价比最高的护眼台灯

l 只要台灯质量过关就是及格的第一步&#xff0c;首先就是有3C质量认证&#xff0c;符合国A或国AA照度标准。l 显色也会是很重要的&#xff0c;光源品质高的产品&#xff0c;显色性不会低于Ra90的&#xff0c;太阳光的显色指数&#xff1d;100&#xff0c;那么意味着显色指数越…

一文详解Paramiko安装与使用

项目要求 定期向特定服务器传输软件运行状况文件&#xff08;基于SFTP&#xff09;&#xff0c;因此计划写一个Python脚本&#xff0c;该脚本首先要定期读取产品运营数据&#xff0c;然后按要求生成数据文件&#xff0c;最后通过 Paramiko 上传到SFTP服务器。 这篇文章是我在实…

【Spring源码】19. 没合适的构造器?找determineCandidateConstructors()!

上篇介绍了instantiateBean()&#xff08;其实这个方法在后面还会再次被调用&#xff09;如果在前两篇的内容结束后都还未获取到构造函数&#xff0c;那么则继续向下执行&#xff0c;调用determineConstructorsFromBeanPostProcessors()方法determineConstructorsFromBeanPostP…

如何确定梯度消失/爆炸和解决梯度消失/爆炸

1、梯度消失的原因和表现1.1、梯度消失的原因&#xff1a;在深层网络中&#xff0c;如果激活函数的导数小于1&#xff0c;根据链式求导法则&#xff0c;靠近输入层的参数的梯度因为乘了很多的小于1的数而越来越小&#xff0c;最终就会趋近于0&#xff0c;例如sigmoid函数&#…

【C++常用算法】STL基础语法学习 | 算数生成算法集合算法

目录 ●accumulate ●fill ●set_intersection ●set_union ●set_difference ●accumulate 1.功能描述&#xff1a; 计算容器内元素累计总和 2.查看accumulate定义下底层代码的函数原型&#xff1a; 3.向vector容器中插入0~100&#xff0c;使用accumulate算法去计算其和…

RabbitMQ的五大常用模型介绍以及SpringAMQP的使用

目录MQ的介绍使用MQ的好处技术对比RabbitMQ的使用Docker启动MQ角色介绍五大常用消息模型使用SpringAMQP模板简单队列模型工作队列模型广播模型 Fanout路由模式 Direct主题模式 TopicMQ的介绍 MQ&#xff0c;MessageQuene即 消息队列&#xff0c;是程序与程序之间的异步通信一种…

spring的IOC与DI小案例

注&#xff1a;本博客用于自学&#xff0c;如有错误&#xff0c;敬请指正。 一、首先要了解的概念 IOC是一种思想&#xff1a;将创建、初始化对象的控制权交给IOC容器 IOC容器&#xff1a;用来装对象的容器 Bean&#xff1a;IOC容器中装的对象 DI&#xff1a;将IOC容器种Bean…

打破光缆资源管理难题

如何打破光缆资源管理难题&#xff0c;将光缆资源价值最大化&#xff0c;相信是每个运维人都关心的焦点问题。 一、背景 全业务发展到今天&#xff0c;我们逐渐意识到&#xff0c;市场竞争的核心已聚焦到传输资源。从拼资源总量到拼资源管理&#xff0c;传统的运维管理模式面临…

【每日一题】【LeetCode】【第九天】存在重复元素

解决之路 题目描述 测试案例&#xff08;部分&#xff09; 第一次 关键就是看是否有重复元素&#xff0c;暴力解法就是双循环&#xff0c;然后有相同元素就返回True&#xff0c;否则就等循环结束&#xff0c;返回False。 但是自己想到了另一个只需要一个循环的解法。用一个…

C++11 简化 “策略模式” 的一种思路

策略模式是一种定义一系列算法的模式&#xff0c;从概念上看&#xff0c;所有这些算法完成的都是相同接口的工作&#xff08;只是实现不同&#xff09;&#xff0c;它可以以相同的方式调用所有的算法&#xff0c;减少了各种算法类与使用算法的类之间的耦合。实践中只要在分析过…

开发者工具中performance面板解析

目录总览设置面板网络性能总览图火焰图&#xff1a;耗费的时间相关信息总览 如图&#xff0c;主要分为以下4个方面 设置面板 1&#xff0c; 不刷新页面进行录制 2&#xff0c;刷新页面进行录制 3&#xff0c;删除性能展示页面 4&#xff0c;上传本地的性能页面 5&#xff0c…

若依mybatis升级mybatis-plus,其他也适用

若依mybatis升级mybatis-plus,其他也适用 本文档记录若依mybatis升级plus,其他也类似 文章目录若依mybatis升级mybatis-plus,其他也适用第一步 修改ruoyi-common的pom.xml第二步 修改ruoyi-admin的application.yml第三步 修改ruoyi-framework的MyBatisConfig.java开始测试1. 修…

一、计算机系统概论

文章目录一、计算机系统简介1.计算机软硬件概念2.计算机系统的层次结构&#xff08;1&#xff09;现代计算机&#xff08;2&#xff09;发展&#xff08;3&#xff09;软硬件分布3.计算机组成和计算机体系结构二、计算机的基本组成1.冯诺依曼计算器2.计算机硬件框图3.计算机工作…

android架构拆分方案-编译相关方案与技术

接上文https://blog.csdn.net/dongyi1988/article/details/128617738直接拆分那么在代码和做包过程中&#xff0c;需要用到分仓&#xff0c;super.img、boot、OTA升级包的拆分与组合&#xff0c;vendor与system相关依赖处理&#xff0c;开机验证链还必须给镜像签名。代码管理定…

VisualODX——ODX数据自动转换工具

在创建ODX数据库的过程中&#xff0c;我们需要录入大量的数据以及应对多种数据格式。这不仅费时费力&#xff0c;而且还需要很高的人力成本&#xff0c;并且其错误率也高&#xff0c;从而导致了效率低下、开发速度缓慢。基于多年的汽车行业诊断经验&#xff0c;Softing开发了Vi…

基于微信小程序的课程分享平台小程序

文末联系获取源码 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏览器…

xv6-lab3: page table

文章目录1.speed up system call2. print page3. Detecting which pages have been accessedwhere is page table?function of page table?how to get arguments from user to kernel? – reference:https://stackoverflow.com/questions/46870509/how-to-pass-a-value-into…

风速记录仪大屏幕液晶显示全中文操作菜单操作简单

风速记录仪功能特点◆本机体积小巧美观&#xff0c;大屏幕液晶显示&#xff0c;全中文操作菜单&#xff0c;操作简单&#xff0c;性能可靠&#xff0c;记录间隔可根据要求从1分至24小时任意设置。&#xff08;但由于存储器空间有限&#xff0c;设置后也可随时查看存储信息&…