1 #include <rtthread.h> 2 #include <string.h> 3 4 #if !defined(SAL_USING_POSIX) 5 #error "Please enable SAL_USING_POSIX!" 6 #else 7 #include <sys/time.h> 8 #include <sys/select.h> 9 #endif 10 #include <sys/socket.h> /* 使用BSD socket,需要包含socket.h头文件 */ 11 #include "netdb.h" 12 13 #define DEBUG_TCP_CLIENT 14 15 #define DBG_ENABLE 16 #define DBG_SECTION_NAME "TCP" 17 #ifdef DEBUG_TCP_CLIENT 18 #define DBG_LEVEL DBG_LOG 19 #else 20 #define DBG_LEVEL DBG_INFO /* DBG_ERROR */ 21 #endif 22 #define DBG_COLOR 23 #include <rtdbg.h> 24 25 #define BUFSZ 1024 26 27 static int started = 0; 28 static int is_running = 0; 29 static char url[256]; 30 static int port = 8080; 31 static const char send_data[] = "This is TCP Client from RT-Thread."; /* 发送用到的数据 */ 32 33 static void tcpclient(void *arg) 34 { 35 int ret; 36 char *recv_data; 37 int bytes_received; 38 int sock = -1; 39 struct hostent *host = RT_NULL; 40 struct sockaddr_in server_addr; 41 42 struct timeval timeout; 43 fd_set readset; 44 45 /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */ 46 host = gethostbyname(url); 47 if (host == RT_NULL) 48 { 49 LOG_E("Get host by name failed!"); 50 return; 51 } 52 53 /* 分配用于存放接收数据的缓冲 */ 54 recv_data = rt_malloc(BUFSZ); 55 if (recv_data == RT_NULL) 56 { 57 LOG_E("No memory"); 58 return; 59 } 60 61 /* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */ 62 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) 63 { 64 /* 创建socket失败 */ 65 LOG_E("Create socket error"); 66 goto __exit; 67 } 68 69 /* 初始化预连接的服务端地址 */ 70 server_addr.sin_family = AF_INET; 71 server_addr.sin_port = htons(port); 72 server_addr.sin_addr = *((struct in_addr *)host->h_addr); 73 rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); 74 75 /* 连接到服务端 */ 76 if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) 77 { 78 /* 连接失败 */ 79 LOG_E("Connect fail!"); 80 goto __exit; 81 } 82 83 started = 1; 84 is_running = 1; 85 86 timeout.tv_sec = 3; 87 timeout.tv_usec = 0; 88 89 while (is_running) 90 { 91 FD_ZERO(&readset); 92 FD_SET(sock, &readset); 93 94 /* Wait for read */ 95 if (select(sock + 1, &readset, RT_NULL, RT_NULL, &timeout) == 0) 96 continue; 97 98 /* 从sock连接中接收最大BUFSZ - 1字节数据 */ 99 bytes_received = recv(sock, recv_data, BUFSZ - 1, 0); 100 if (bytes_received < 0) 101 { 102 /* 接收失败,关闭这个连接 */ 103 LOG_E("Received error, close the socket."); 104 goto __exit; 105 } 106 else if (bytes_received == 0) 107 { 108 /* 打印recv函数返回值为0的警告信息 */ 109 LOG_W("Received warning, recv function return 0."); 110 continue; 111 } 112 else 113 { 114 /* 有接收到数据,把末端清零 */ 115 recv_data[bytes_received] = '\0'; 116 117 if (rt_strcmp(recv_data, "q") == 0 || rt_strcmp(recv_data, "Q") == 0) 118 { 119 /* 如果是首字母是q或Q,关闭这个连接 */ 120 LOG_I("Got a 'q' or 'Q', close the socket."); 121 goto __exit; 122 } 123 else 124 { 125 /* 在控制终端显示收到的数据 */ 126 LOG_D("Received data = %s", recv_data); 127 } 128 } 129 130 /* 发送数据到sock连接 */ 131 ret = send(sock, send_data, rt_strlen(send_data), 0); 132 if (ret < 0) 133 { 134 /* 接收失败,关闭这个连接 */ 135 LOG_I("send error, close the socket."); 136 goto __exit; 137 } 138 else if (ret == 0) 139 { 140 /* 打印send函数返回值为0的警告信息 */ 141 LOG_W("Send warning, send function return 0."); 142 } 143 } 144 145 __exit: 146 if (recv_data) 147 { 148 rt_free(recv_data); 149 recv_data = RT_NULL; 150 } 151 if (sock >= 0) 152 { 153 closesocket(sock); 154 sock = -1; 155 } 156 started = 0; 157 is_running = 0; 158 return; 159 } 160 161 static void usage(void) 162 { 163 rt_kprintf("Usage: tcpclient -h <host> -p <port>\n"); 164 rt_kprintf(" tcpclient --stop\n"); 165 rt_kprintf(" tcpclient --help\n"); 166 rt_kprintf("\n"); 167 rt_kprintf("Miscellaneous:\n"); 168 rt_kprintf(" -h Specify host address\n"); 169 rt_kprintf(" -p Specify the host port number\n"); 170 rt_kprintf(" --stop Stop tcpclient program\n"); 171 rt_kprintf(" --help Print help information\n"); 172 } 173 174 static void tcpclient_test(int argc, char** argv) 175 { 176 rt_thread_t tid; 177 178 if (argc == 1 || argc > 5) 179 { 180 LOG_I("Please check the command you entered!\n"); 181 goto __usage; 182 } 183 else 184 { 185 if (rt_strcmp(argv[1], "--help") == 0) 186 { 187 goto __usage; 188 } 189 else if (rt_strcmp(argv[1], "--stop") == 0) 190 { 191 is_running = 0; 192 return; 193 } 194 else if (rt_strcmp(argv[1], "-h") == 0 && rt_strcmp(argv[3], "-p") == 0) 195 { 196 if (started) 197 { 198 LOG_I("The tcpclient has started!"); 199 LOG_I("Please stop tcpclient firstly, by: tcpclient --stop"); 200 return; 201 } 202 203 if (rt_strlen(argv[2]) > sizeof(url)) 204 { 205 LOG_E("The input url is too long, max %d bytes!", sizeof(url)); 206 return; 207 } 208 rt_memset(url, 0x0, sizeof(url)); 209 rt_strncpy(url, argv[2], rt_strlen(argv[2])); 210 port = atoi(argv[4]); 211 } 212 else 213 { 214 goto __usage; 215 } 216 } 217 218 tid = rt_thread_create("tcp_client", 219 tcpclient, RT_NULL, 220 2048, RT_THREAD_PRIORITY_MAX/3, 20); 221 if (tid != RT_NULL) 222 { 223 rt_thread_startup(tid); 224 } 225 return; 226 227 __usage: 228 usage(); 229 } 230 231 #ifdef RT_USING_FINSH 232 MSH_CMD_EXPORT_ALIAS(tcpclient_test, tcpclient, 233 Start a tcp client. Help: tcpclient --help); 234 #endif 235