1)实验平台:正点原子开拓者FPGA 开发板
2)摘自《开拓者 Nios II开发指南》官方微信号,获取更多资料:正点原子
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/index.html
第二十三基于NicheStack的TCP客户端实验
上一章我们使用NicheStack实现了一个简单的TCP服务器程序,本章我们继续使用
NicheStack实现一个简单的TCP客户端,网络调试助手做TCP服务器,实验中我们通过电脑端的
网络调试助手给开发板发送数据,开发板接收并在控制台上打印接收到的数据,同时将接收到
的数据环回给网络调试助手。本章分为以下几个部分:
23.1 简介
23.2 实验任务
23.3 硬件设计
23.4 软件设计
23.5 下载验证
简介
关于TCP的介绍可以参考上章《基于NicheStack的TCP服务器实验》的简介部分。
实验任务
本章的实验任务是使用NicheStack实现简单的TCP客户端,其功能是将作为TCP服务器的网
络调试助手发送给开发板的数据环回至网络调试助手。
硬件设计
本章的TCP实验硬件部分可以基于《基于NicheStack的简单socket服务器实验》,无需修
改。
软件设计
软件设计部分与上一章《基于NicheStack的TCP服务器实验》的区别不大,可以在上一章
的软件设计部分的基础上修改。
重命名tcp_server.c为tcp_client.c。并将其内容替换如下:
1 #include <stdio.h>
2 #include <string.h>
3 #include <ctype.h>
4
5 #include "includes.h" //MicroC/OS-II definitions
6 #include "simple_socket_server.h" //Simple Socket Server definitions
7 #include "alt_error_handler.h" //错误处理
8 /* Nichestack definitions */
9 #include "ipport.h"
10 #include "tcpport.h"
11
12 /*
13 * sss_reset_connection()
14 *
15 * 复位SSSConn结构体成员
16 */
17 void sss_reset_connection(SSSConn* conn) {
18 memset(conn, 0, sizeof(SSSConn));
19
20 conn->fd = -1;
21 conn->state = READY;
22 conn->rx_wr_pos = conn->rx_buffer;
23 conn->rx_rd_pos = conn->rx_buffer;
24 return;
25 }
26
27 /*
28 * sss_handle_receive()
29 *
30 * 处理接收自客户端的信息,实现环回功能,并打印接收到的信息
31 * 如果输入quit就结束连接
32 */
33 void sss_handle_receive(SSSConn* conn) {
34 const char quit[] = "quit";
35
36 while (conn->state != CLOSE) {
37 if (recv(conn->fd, conn->rx_buffer, SSS_RX_BUF_SIZE -1, 0) > 0) {
38 conn->rx_rd_pos = conn->rx_buffer;
39 conn->rx_wr_pos = conn->rx_buffer;
40 printf("[sss_handle_receive] print RX data: %s\n", conn->rx_rd_pos);
41 s(conn->fd, conn->rx_wr_pos, strlen(conn->rx_wr_pos), 0);
42 }
43
44 if (strcmp(conn->rx_rd_pos, quit) == 0) {
45 conn->close = 1;
46 }
47 conn->state = conn->close ? CLOSE : READY; //如果输入quit就结束连接
48 memset(conn->rx_buffer, 0, SSS_RX_BUF_SIZE); //清空rx_buffer
49 }
50
51 printf("[sss_handle_receive] closing connection\n");
52 close(conn->fd);
53 sss_reset_connection(conn);
54
55 return;
56 }
57
58 /*
59 * SSSSimpleSocketServerTask()
60 *
61 * 创建 MicroC/OS-II任务,实现TCP客户端功能
62 */
63 void SSSSimpleSocketServerTask() {
64 int sockfd;
65 struct sockaddr_in servaddr;
66 static SSSConn conn;
67 const char *servip = "192.168.1.89";
68
69 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
70 alt_NetworkErrorHandler(EXPANDED_DIAGNOSIS_CODE,
71 "[sss_task] Socket creation failed");
72 }
73
74 memset(&servaddr, '0', sizeof(servaddr));
75 //构建服务器地址信息
76 servaddr.sin_family = AF_INET;
77 servaddr.sin_port = htons(8080);
78 if (inet_pton(AF_INET, servip, &servaddr.sin_addr) != 0) {
79 printf("\nInvalid address/ Address not supported \n");
80 return;
81 }//将服务器IP地址转换成二进制写进servaddr.sin_addr
82
83 sss_reset_connection(&conn);
84
85 if (connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0) {
86 alt_NetworkErrorHandler(EXPANDED_DIAGNOSIS_CODE, "connect failed");
87 } else {
88 conn.fd = sockfd;
89 printf("connected to %s\n", inet_ntoa(servaddr.sin_addr));
90 }
91
92 while (1) {
93 sss_handle_receive(&conn);
94 } /* while(1) */
95 }
代码第67行为服务器的IP地址。从代码第77行可知,我们通过8080端口访问服务器,第78
行 的 inet_pton 函 数 将 IP 字 符 串 转 换 成 二 进 制 形 式 , 写入到 servaddr.sin_addr 中 。
SSSSimpleSocketServerTask()任务函数即TCP客户端任务函数。在sss_handle_receive函数中,
当连接状态不处于close时,就一直接收和环回数据,直到接收到“quit”数据时(相当于断
开命令),客户端断开连接。
经过以上修改后,软件设计部分就完成了。
下载验证
修改完软件工程,接下来我们就将该实验下载至我们的开拓者开发板进行验证。
首先我们打开网络调试助手,设置如图 23.5.1所示并点击“打开”按钮。然后我们用一根
网线将开发板和电脑进行连接,然后连接JTAG和电源,开发板上电后我们在Quartus II软件中
将qsys_eth.sof文件下载至我们的开拓者开发板,qsys_eth.sof下载完成后,我们就将
qsys_eth.elf文件系统下载至我们的开拓者开发板,下载完成后,控制台打印信息如图 23.5.2
所示。
图 23.5.1 网络调试助手设置
图 23.5.2 启动TCP客户端信息
如果没有出现“connected to 192.168.1.89”,而是在等待了很长时间后出现下图所示
信息:
图 23.5.3 连接失败信息
我们可以先暂时关闭防火墙。打开控制面板,“查看方式”选择“大图标”,点击“Windows
Defer防火墙”,如下图所示:
图 23.5.4 打开Windows Defer防火墙
进入下图所示界面:
图 23.5.5 启用或关闭Windows Defer防火墙
点击“启用或关闭Windows Defer防火墙”,进入下图所示界面。
图 23.5.6 关闭Windows Defer防火墙
在“公用网络设置”下勾选“关闭Windows Defer防火墙”,点击“确定”按钮,再次
下载elf文件,即可连接成功,如果还是连接不成功,可以试着将“专用网络设置”的防火墙
关闭。
连接成功后,网络调试助手显示一些信息,如下图所示,我们在网络调试助手的发送文本
框中输入数据“正点原子”并点击发送。
图 23.5.7 显示连接成功信息&输入发送信息
结果如下图所示:
图 23.5.8 环回结果
可以看到网络调试助手接收到了TCP服务端返回的信息。与此同时,控制台打印如下信息:
图 23.5.9 控制台打印接收信息
本章实验结束。需要说明的是,输入“quit”后客户端会结束连接,此时,需要重新下载
elf文件才能重新建立连接。