10

UEFI开发探索54 – UEFI与网络4(IPv4)

 4 years ago
source link: http://yiiyee.cn/blog/2020/04/10/uefi%e5%bc%80%e5%8f%91%e6%8e%a2%e7%b4%a254-uefi%e4%b8%8e%e7%bd%91%e7%bb%9c4/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

UEFI开发探索54 – UEFI与网络4(IPv4)

请保留-> 【原文:  https://blog.csdn.net/luobing4365http://yiiyee.cn/blog/author/luobing/】

本篇主要讨论怎么使用StdLib的库函数编写TCP4的代码。

上一篇中直接使用UEFI提供的TCP4 Protocol编写代码,比较复杂,需要自己重新构建所有代码。我们还是希望能够直接使用标准的Socket库来编程,这样可以直接复用以前编写的Socket代码,减少编程的工作量。

1 BSD Socket接口

StdLib中提供的是标准BSD Socket接口,允许不同主机或同一计算机的不同进程之间的通信,是事实上的连接互联网的标准接口。

BSD Socket中要求的API接口,在UEFI的实现中基本都提供了。主要的头文件如下(StdLib\Include下):

<sys/socket.h>  socket 的核心函数和数据结构;
<netinet/in.h>  互联网地址族,AF_INET 和AF_INET6 地址家族和他们对应的协议家族 PF_INET 和 PF_INET6,包括IP地址以及TCP和UDP端口号;
<arpa/inet.h> 和IP地址相关的一些函数,比如地址转换的inet_pton()等;

由于UEFI并非完整的操作系统,也有很多BSD Socket中的API没有实现,比如针对计算机上程序间的本地通信的un.h。这些没有实现的函数,大部分是与网络通信无关,对我们的UEFI网络编程影响不大。

大部分的程序员应该都编写过Socket的代码,UEFI下编写的方法其实差不多。如果有需要,是可以把以前编写的代码直接移植过来的。

2 函数介绍

Socket中提供的库函数,介绍如下(以下内容只针对UEFI平台有效)。

int socket(IN INT32 domain, IN INT32 type, IN INT32 protocol);
  ●功能  创造某种类型的套接字,分配系统资源。
  ●参数  domain:确定协议族,PF_INET为IPv4,PF_INET6为IPv6
          type: 类型,支持SOCK_STREAM、SOCK_DGRAM和SOCK_RAW;
          protocol: 指定传输层所用协议。IPPROTO_TCP,type必须指定为SOCK_STREAM; IPPROTO_UDP,type必须指定为SOCK_DGRAM;0-254,type为SOCK_RAW,值的含义可参考:https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml
  ●返回值  返回socket句柄,如果返回-1,则表明有错误发生

int bind ( IN int s, IN const struct sockaddr * name, IN socklen_t namelen );
●功能  将socket句柄和套接字地址结构相连。
●参数  s: scoket句柄,由socket()函数返回;
          name: 指向sockaddr 结构体的指针,代表要绑定的地址;
          namelen: sockaddr结构体的大小
 ●返回值  0表示操作成功,-1表示失败

int listen (IN int s, IN int backlog );
●功能  监听连接,适用于面向连接的模式,比如类型为SOCK_STREAM的套接字。
  ●参数  s: scoket句柄,由socket()函数返回;
          backlog: 能够等待的最大连接数目;  
  ●返回值  0表示操作成功,-1表示失败

int connect ( int s, const struct sockaddr * address, socklen_t address_len );
●功能  通过网络建立连接
  ●参数  s: scoket句柄,由socket()函数返回;
          address: 网络地址;
          namelen: 网络地址的字节长度
  ●返回值  0表示操作成功,-1表示失败

int accept ( int s, struct sockaddr * address, socklen_t * address_len );
●功能  接收网络连接,一般用于服务端程序
  ●参数  s: scoket句柄,由socket()函数返回;
          address: 网络地址;
          namelen: 网络地址的字节长度
  ●返回值  0表示操作成功,-1表示失败

ssize_t  recv ( int s, void * buffer, size_t length, int flags );
●功能  接收数据
  ●参数  s: scoket句柄,由socket()函数返回;
          buffer: 用来接收数据的缓冲区;
          flags: 用来控制接收方式的标志,比如接收OOB(带外数据)。一般设为0;
  ●返回值  -1表示失败,其他大于-1的整数值表示接收到的数据个数

ssize_t  send ( int s, CONST void * buffer, size_t length, int flags );
●功能  发送数据
  ●参数  s: scoket句柄,由socket()函数返回;
          buffer: 用来发送数据的缓冲区;
          flags: 用来控制发送方式的标志,比如发送OOB(带外数据)。一般设为0;
  ●返回值  -1表示失败,其他大于-1的整数值表示发送的数据个数

其他函数,包括recvfrom()、sendto()、setsockopt()等,在本篇的例程中没有用到,可以查询相关的资料。

3 编写程序

我准备的例子中,服务端用网络调试助手,客户端用UEFI的NT32模拟环境。当然,也可以写个服务端的代码,能更好地展示网络编程的过程,找时间再写吧。

TCP的网络服务端代码的编写流程一般为:

1) 使用socket()创建Socket;
2) 使用bind(),把Socket和本机的IP、TCP端口绑定;
3) 为客户端的连接创建等待队列;
4) 循环处理连接,通过accept()接收客户端的连接;
5) 使用recv()或send()接收、发送数据;
6) 使用close()关闭Socket,终止通信。

TCP客户端编写流程为:

1) 使用socket()创建Socket;
2) 使用connect()向服务端发送连接请求,等待回应,并向下执行;
3) 循环处理连接,使用recv ()或send()接收、发送数据;
4) 使用close()关闭Socket,终止通信。

UEFI的代码编写,基本按照上述的流程来写的,具体可以查看提供的例程。TCP通信的函数代码中,全部使用了StdLib中的函数。

编译命令如下:

C:\MyWorkspace> build -p RobinPkg\RobinPkg.dsc -a IA32 -m RobinPkg\Applications\stdEchoTcp4\stdEchoTcp4.inf

意外的是,编译的时候会报错误。查看了下报错位置,是由\StdLib\BsdSocketLib\ns_addr.c中的line 83行语句引起的:

if ((cp = strchr(buf, ‘:’)) && 

因为在条件表达式内赋值,引发了C4706的警告,修正起来也很简单。不过,我不想动StdLib的源码,采用了修改编译选项的方式来解决它。

在conf\tool_def.txt中,找到DEBUG_VS2015x86_IA32_CC_FLAGS的赋值行(我一般编译的时候是用debug编译的,也就是使用-b DEBUG选项。如果是Release,则修改DEBUG_VS2015x86_IA32_CC_FLAGS的赋值语句),把/W4改为/W3即可。

4 测试程序

搭建网络测试环境的方法,在之前的博客中已经讨论过了,这里不再重复。

1) 启动服务端程序

图1 服务端

2 启动UEFI客户端程序

图2 客户端

3 通讯测试

图3 发送接收测试

百度云链接:https://pan.baidu.com/s/1gccSosw8_UAGTI5gZPnLCA
提取码:dx23
文件在 FF RobinPkg/ RobinPkg /Applications/stdEchoTCP4

839 total views, 2 views today


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK