【FFH】OpenHarmony与苹果的梦幻联动——服务器端(上) 原创 精华

Wait_Aurora
发布于 2022-4-26 21:43
浏览
4收藏

一、前言

承接上篇文章的项目介绍,本篇文章将详细介绍如何在小熊派搭建TCP服务器,处理来自各种客户端的请求。本篇文章适合于小型系统和标准系统,大家可以将本项目移植到符合以上条件的开发板上。配置好对应的编译规则即可。

二、准备工作

1、小熊派(BearPi-HM Micro)一台

2、已经配置好小熊派开发环境的电脑一台

3、将小熊派接入到局域网

三、流程简介

编写TCP服务器的C文件 --> 配置BUILD.gn --> 将我们的代码添加编译–>编译烧录

四、网络开发基础知识

在OpenHarmony上进行网络开发与在Linux上进行网络开发十分相似,采用的是C语言的套接字(Socket)开发。

进行网络开发之前,如果没有相关基础,建议先了解一下OSI网络模型与TCP/IP协议的关系。本次用到的是用Socket进行传输层的开发,使用了到了一点点应用层HTTP的协议。

4.1 什么是Socket

在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。

总结为一句就是:socket就是整合好TCP/IP协议的一个工具。让我们无需过度关注于底层协议的实现,直接用封装好的socket就行了

4.2 TCP通信流程

在开始使用socket之前,我们要知道TCP服务器端与TCP客户端进行通信的流程。

【FFH】OpenHarmony与苹果的梦幻联动——服务器端(上)-鸿蒙开发者社区

我们小熊派要实现的是图中的9右半部分,即TCP服务器端。我们一步一步的看,每一步都有对应的代码来实现。

第一步:socket()函数用来创建socket套接字,可以理解为面对对象中的创建对象,但是不等同。

第二步:bind()函数用来绑定IP和端口,即选择你的TCP服务器在哪个IP和端口提供服务。

第三步:listen()函数用来监听上一步中选择的IP和端口。

第四步:accept()函数用来等待来自客户端的连接,即进入阻塞状态。

第五步:read()函数会在有客户请求时,读取客户端发送的请求数据。

第六步:write()函数可以给客户端返回数据,该操作可选,也可以不给客户端返回任何数据。

第七步:read()和write()操作可以一直反复执行,即互相不断通信,当通信完成时,执行close函数关闭套接字。

4.3 相关函数讲解

4.3.1创建socket套接字

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

参数介绍

  • domain:协议域,又称协议族(family),常用的协议族有 AFL INET、AF INET6、AF LOCAL(或称AF UNIX, Unix成socket) AF ROUTE 等。协议族决定了 socket 的地址类型,在通信中必须采用对应的地址,如AF INET 決定了要用 ipv4 地址 (32位的》与端口号(16位的)的组合,AF UNIX 決定了要用一个绝对路径名作为地址。
  • type:指定 Socket 类型。常用的 socket 类型有 SOCK STREAM、SOCK DGRAM、SOCK RAW 、SOCK PACKET、 SOCK SEQPACKET 等。流式 socket (SOCK STREAM)是一种面向连接的 Socket, 针对于面向连接的 TCP 服务应用。数据报式 socket(SOCK DGRAM) 是一种无连接的 Socket,对应于 无连接的 UDP 服务应用。
  • protocol: 指定协议。常用协议有 IPPROTO TCP、IPPROTO UDP、IPPROTO STCP、IPPROTO TIPC 等,分别对应TCP 传输协议,UDP 传输协议、STCP 传输协议、TIPC 传输协议。参数为o时,会自动选择第二个参数类型对应的默认协议。

注意:type 和protocol 不可以随意组合,如SOCK STREAM 不可以跟 1PPROTOUDP 组合。
返回值: 如果调用成功就返口新创建的套接字的描述符,如果大败就返回INVALID SOCKET
(Linux 下失败返回-1).

4.3.2绑定端口函数

int bind(int socketfd,const struct sockaddr *addr,socklen_t addrlen)

参数介绍

  • socketfd:
    —个标识己连接套接口的描述字。
  • address:是个sockaddr结构指针,该结构中包含了要结合的地址和端口号。
  • address_len:确定 address 缓冲区的长度。

注意:其中 sockaddr这个地址结构根据地址创建 socket 时的地址协议族的不同而不同。

返回值:如果函数执行成功,返回值为0,否则为SOCKET_ERROR。

4.3.3开始监听函数

int listen(int socketfd,int backlog)

参数介绍

  • socketfd:要监听的socket描述字
  • backlog:相应socket可以排队的最大连接个数

4.3.4等待连接阻塞函数

int accept(int socketfd,struct sockaddr *addr, socklen_t *addrlen);

参数介绍

  • socketfd:就是上面解释中的监听套接字,这个套接字用来监听一个端口,当有一个客户与服务
    器连接时,它使用这个个端口号,而此时这个端口号正与这个套接字关联。当然客户不知道套
    接字这些细节,已只知道一个地址和一个端口号。
  • sockaddr:结果参数,它用来接受一个返回值,这返回值指定客户端的地址,当然这个地址是
    通过某个地址结构来描述的,用户应该知道这一个什么样的地址结构。如果对客户的地址不感兴
    趣,那么可以把这个值设置为NULL。
  • len:它也是结果的参数,用来接受上述 addr 的结构的大小的,已指明 addr 结构所占有的宇节
    个数。同样的,它也可以被设置为NULL

注意:accept默认会阻塞进程,直到有一个客户连接建立后返回,它返回的是一个新可用的套接字,这个套接字是连接套接字。

返回值:成功返回客户端的文件猫述符,失败返回-1。一如果accept成功返回,则服务器与容户
己经正确建立连接了,此时服务器通过accept返口的套接字来完成与客户的通信。
5.连接函数

int connnect(int sockfd,const struct sockaddr *addr,socklen_t addrlen)

参数介绍

  • socketfd:客户端socket的描述字。
  • socketaddr:服务器的socket地址。
  • addrlen:socket地址的长度

4.3.5 发送函数

发送函数有两个

ssize_t write(int sockfd,const void *buf,szie_t nbytes);

参数介绍

  • sockfd为要写入文件的描述符。
  • buf为要写入数据的缓冲区地址。
  • nbytes为要写入的数据的字节书。

返回值:成功返回写入的字节数,失败返回-1。

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

参数介绍

  • sockfd为要写入文件的描述符。
  • buf为要写入数据的缓冲区地址。
  • len为要写入的数据的字节书。
  • flags有以下选择,MSG_ DONTROUTE 为不查找路由表;MSG_OOB为接受或发送带外数据 ;MSG PEEK为查看数据,且不从系统缓冲区移走数据;MSG WAITALL为等待任何数据;0和write函数的操作一样。

返回值:成功返回写入的字节数,失败返回-1。

4.3.6 接受函数

接受函数同样有两个

ssize_t read(int sockfd,const void *buf,szie_t nbytes);

参数介绍

  • sockfd为要读取文件的描述符。
  • buf为要读取数据的缓冲区地址。
  • nbytes为要读取的数据的字节书。

返回值:成功返回读取到的字节数,失败返回-1。

int recv(int sockfd,const void *buf,int len,int flags)

参数介绍

  • sockfd为要写入文件的描述符。
  • buf为要写入数据的缓冲区地址。
  • len为要写入的数据的字节书。
  • flags有以下选择,MSG_ DONTROUTE 为不查找路由表;MSG_OOB为接受或发送带外数据 ;MSG PEEK为查看数据,且不从系统缓冲区移走数据;MSG WAITALL为等待任何数据;0和write函数的操作一样。

返回值:成功返回写入的字节数,失败返回-1。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-12-21 16:35:08修改
5
收藏 4
回复
举报
1条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

终于等到楼主的文章了!

回复
2022-4-27 09:39:30
回复
    相关推荐