作业要求:
通过编程实现:
- 使用 login 命令登录上服务器聊天室,并将服务器返回的信息通过串口打印出来
- 使用 say 命令通知服务器你的个人姓名和作业时间 “My name is Yqiu,I’m doing this job at 20180730”,并
将服务器返回的信息打印出来 - 使用 look 命令查看聊天室人员,并将服务器返回的信息打印出来
- 使用 who 命令查看我是谁,并将服务器返回的信息打印出来
- 使用 say 命令告诉服务器我看到有哪些人在聊天室
- 使用 say 命令告诉服务器我准备退出了
- 使用 logout 退出聊天室
由每个人独立完成,完成后将串口打印截图发群里。
开发环境说明:qemu虚拟机环境 env 0.7.0
问题总结:
- 作为命令行输入时,如果同时作为串口输出,如何切换回命令行呢?好像没办法。网友说回车一下就可以。意识是命令行的线程没有结束。待验证。
- 连接服务器后,好像时间挺长的,等待每一条命令。调整把命令放在最前面,好像点,接收放在后面。
- 数据错位,并不是你发一条,服务器就给你回一条对应的信息立即马上,可能会先收到其他信息,所以需要处理,而不只是按顺序进行。Look who时候,发两次数据。
- Look 时候的的结果,也是有回车换行的,在数据封装的时候也需要处理,否则的话,那些数据都变成了命令。服务器就会返回无法识别。用strtok来实现,但因为strtok实现原理是用/0 替代,就是字符串结束标志,所以不太好用,因为最后发送时候,需要用strlen 来检测字符串长度,这个‘\0’是有影响的。最后直接写个替换程序,把
换成空格 - 连接失败的话,试着关闭防火墙,并关闭网络共享,再重新打开网络共享。。另外如果是wifi 的话,看看是不是连接到其他网络上,不是之前设置的那个共享的网络了。
- 刚开始等待很长时间,可能是聊天室没人。换个名字,再试试。```/*
- 程序清单:tcp 客户端
* - 这是一个 tcp 客户端的例程
- 导出 tcpclient 命令到控制终端
- 命令调用格式:tcpclient URL PORT
- URL:服务器地址 PORT::端口号
- 程序功能:接收并显示从服务端发送过来的信息,接收到开头是 ‘q’ 或 ‘Q’ 的信息退出程序
*/include
include / 使用BSD socket,需要包含socket.h头文件 /
include “netdb.h”
define BUFSZ 1024
define MYID “666765”
static const char *command[7]=
{
“login 666765
“,
// “say what are you doing
“,
“say My name is fanxiaojie,I’m doing the job at 20180801
“,
“look
“,
“who
“,
“say i can seen “,
“say I am quiting
“,
“logout
“
};
void command_test(int sock,char command,char recv_data)
{
int ret;
// rt_kprintf(“the command is: %s the length is %d
“,command,strlen(command));
rt_kprintf(“send error,close the socket.
“);
rt_free(recv_data);
// break;
}
else if (ret == 0)
{
/* 打印send函数返回值为0的警告信息 */
rt_kprintf("<br> Send warning,send function return 0. <br>");
}
}
static const char send_data[] = “This is TCP Client from RT-Thread.”; / 发送用到的数据 /
char look[50];
void tcpclient(int argc, char *argv)
{
int ret;
char recv_data;
struct hostent host;
int sock, bytes_received;
struct sockaddr_in server_addr;
const char url;
int port;
int command_count =0;
/ if (argc < 3)
{
rt_kprintf(“Usage: tcpclient URL PORT
“);
rt_kprintf(“Like: tcpclient 192.168.12.44 5000
“);
return ;
}/
url = "183.193.243.90";//argv[1];
port = 11222;//strtoul(argv[2], 0, 10);
/* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */
host = gethostbyname(url);
/* 分配用于存放接收数据的缓冲 */
recv_data = rt_malloc(BUFSZ);
if (recv_data == RT_NULL)
{
rt_kprintf("No memory<br>");
return;
}
/* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
/* 创建socket失败 */
rt_kprintf("Socket error<br>");
/* 释放接收缓冲 */
rt_free(recv_data);
return;
}
/* 初始化预连接的服务端地址 */
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
/* 连接到服务端 */
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
/* 连接失败 */
rt_kprintf("Connect fail!<br>");
closesocket(sock);
/*释放接收缓冲 */
rt_free(recv_data);
return;
}
bytes_received = recv(sock, recv_data, BUFSZ - 1, 0);
recv_data[bytes_received] = '\0';
/* 在控制终端显示收到的数据 */
rt_kprintf("<br>Received data = %s", recv_data);
char lookstring[100];
rt_bool_t start_send = 1;
while (1)
{
if((command_count < 7)&&(start_send == 1))
{
if (command_count == 4) //i can see
{
rt_sprintf(&lookstring[0],"%s%s in this room <br>",command[command_count],look);
command_test(sock,lookstring,recv_data);
}
// rt_kprintf("command_count is %d <br>",command_count);
else
{
command_test(sock,command[command_count],recv_data);
}
start_send = 0;
}
/* 从sock连接中接收最大BUFSZ - 1字节数据 */
bytes_received = recv(sock, recv_data, BUFSZ - 1, 0);
if (bytes_received < 0)
{
/* 接收失败,关闭这个连接 */
closesocket(sock);
rt_kprintf("<br>received error,close the socket. <br>");
/* 释放接收缓冲 */
rt_free(recv_data);
break;
}
else if (bytes_received == 0)
{
/* 默认 recv 为阻塞模式,此时收到0认为连接出错,关闭这个连接 */
closesocket(sock);
rt_kprintf("<br>received error,close the socket. <br>");
/* 释放接收缓冲 */
rt_free(recv_data);
break;
}
/* 有接收到数据,把末端清零 */
recv_data[bytes_received] = '\0';
char *chartemp;
if (strncmp(recv_data, "q", 1) == 0 || strncmp(recv_data, "Q", 1) == 0)
{
/* 如果是首字母是q或Q,关闭这个连接 */
closesocket(sock);
rt_kprintf("<br> got a 'q' or 'Q',close the socket. <br>");
/* 释放接收缓冲 */
rt_free(recv_data);
break;
}
else
{
/* 在控制终端显示收到的数据 */
rt_kprintf("<br>Received data = %s", recv_data);
if (command_count ==2) //look //The following are in this room:
{
if(rt_strstr(recv_data,MYID) != NULL)
{
//chartemp=strchr(recv_data,':');
// rt_strncpy(look,chartemp,strlen(chartemp));
rt_strncpy(look,recv_data,strlen(recv_data));//strlen(recv_data));
replace(look);
rt_kprintf("look[] is %s<br>",look);
command_count++;
start_send = 1;
}
}
else if (command_count ==3)
{
if(rt_strstr(recv_data,MYID) != NULL)
{
command_count++;
start_send = 1;
}
}
else
{
command_count++;
start_send = 1;
}
}
/* 发送数据到sock连接 */
/* ret = send(sock, send_data, strlen(send_data), 0);
if (ret < 0)
{
/* 接收失败,关闭这个连接
closesocket(sock);
rt_kprintf("<br>send error,close the socket. <br>");
rt_free(recv_data);
break;
}
else if (ret == 0)
{
/* 打印send函数返回值为0的警告信息
rt_kprintf("<br> Send warning,send function return 0. <br>");
}*/
/*if(command_count < 7)
{
// rt_kprintf("command_count is %d <br>",command_count);
command_test(sock,&command[command_count],recv_data);
command_count++;
}*/
}
return;
}
MSH_CMD_EXPORT(tcpclient, a tcp client sample);
void replace(char src_data)
{
int i=0;
while (i<strlen(src_data))
{
if((src_data != ‘
‘) || (src_data != ‘ ‘))
{
i++;
}
else
{
src_data=” “;
}
}
}
```
下载附件 第一周任务:聊天客户端.pdf