tcpserver.c 4.5 KB
Newer Older
B
Bernard Xiong 已提交
1
#include <rtthread.h>
2 3 4 5

//#include <lwip/sockets.h> /* 使用BSD Socket接口必须包含sockets.h这个头文件 */
#include <sys/socket.h> /* 使用BSD socket,需要包含sockets.h头文件 */
#include "netdb.h"
B
Bernard Xiong 已提交
6 7 8 9 10 11 12 13 14

static const char send_data[] = "This is TCP Server from RT-Thread."; /* 发送用到的数据 */
void tcpserv(void* parameter)
{
   char *recv_data; /* 用于接收的指针,后面会做一次动态分配以请求可用内存 */
   rt_uint32_t sin_size;
   int sock, connected, bytes_received;
   struct sockaddr_in server_addr, client_addr;
   rt_bool_t stop = RT_FALSE; /* 停止标志 */
15
   int ret;
B
Bernard Xiong 已提交
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78

   recv_data = rt_malloc(1024); /* 分配接收用的数据缓冲 */
   if (recv_data == RT_NULL)
   {
       rt_kprintf("No memory\n");
       return;
   }

   /* 一个socket在使用前,需要预先创建出来,指定SOCK_STREAM为TCP的socket */
   if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
   {
       /* 创建失败的错误处理 */
       rt_kprintf("Socket error\n");

       /* 释放已分配的接收缓冲 */
       rt_free(recv_data);
       return;
   }

   /* 初始化服务端地址 */
   server_addr.sin_family = AF_INET;
   server_addr.sin_port = htons(5000); /* 服务端工作的端口 */
   server_addr.sin_addr.s_addr = INADDR_ANY;
   rt_memset(&(server_addr.sin_zero),8, sizeof(server_addr.sin_zero));

   /* 绑定socket到服务端地址 */
   if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
   {
       /* 绑定失败 */
       rt_kprintf("Unable to bind\n");

       /* 释放已分配的接收缓冲 */
       rt_free(recv_data);
       return;
   }

   /* 在socket上进行监听 */
   if (listen(sock, 5) == -1)
   {
       rt_kprintf("Listen error\n");

       /* release recv buffer */
       rt_free(recv_data);
       return;
   }

   rt_kprintf("\nTCPServer Waiting for client on port 5000...\n");
   while(stop != RT_TRUE)
   {
       sin_size = sizeof(struct sockaddr_in);

       /* 接受一个客户端连接socket的请求,这个函数调用是阻塞式的 */
       connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size);
       /* 返回的是连接成功的socket */

       /* 接受返回的client_addr指向了客户端的地址信息 */
       rt_kprintf("I got a connection from (%s , %d)\n",
                  inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));

       /* 客户端连接的处理 */
       while (1)
       {
           /* 发送数据到connected socket */
79
           ret = send(connected, send_data, strlen(send_data), 0);
B
Bernard Xiong 已提交
80 81 82
           if (ret < 0)
           {
                /* 发送失败,关闭这个连接 */
83
                closesocket(connected);
B
Bernard Xiong 已提交
84 85 86 87 88 89 90 91 92
                rt_kprintf("\nsend error,close the socket.\r\n");
                break;
           }
           else if (ret == 0)
           {
                /* 打印send函数返回值为0的警告信息 */
                rt_kprintf("\n Send warning,send function return 0.\r\n");
           }

B
Bernard Xiong 已提交
93 94
           /* 从connected socket中接收数据,接收buffer是1024大小,但并不一定能够收到1024大小的数据 */
           bytes_received = recv(connected,recv_data, 1024, 0);
95
           if (bytes_received < 0)
B
Bernard Xiong 已提交
96 97
           {
               /* 接收失败,关闭这个connected socket */
98
               closesocket(connected);
B
Bernard Xiong 已提交
99
               break;
B
Bernard Xiong 已提交
100 101 102 103 104 105 106
           }
           else if (bytes_received == 0)
           {
               /* 打印recv函数返回值为0的警告信息 */
               rt_kprintf("\nReceived warning,recv function return 0.\r\n");
               continue;
           }
B
Bernard Xiong 已提交
107 108 109 110 111 112

           /* 有接收到数据,把末端清零 */
           recv_data[bytes_received] = '\0';
           if (strcmp(recv_data , "q") == 0 || strcmp(recv_data , "Q") == 0)
           {
               /* 如果是首字母是q或Q,关闭这个连接 */
113
               closesocket(connected);
B
Bernard Xiong 已提交
114 115 116 117 118
               break;
           }
           else if (strcmp(recv_data, "exit") == 0)
           {
               /* 如果接收的是exit,则关闭整个服务端 */
119
               closesocket(connected);
B
Bernard Xiong 已提交
120 121 122 123 124 125
               stop = RT_TRUE;
               break;
           }
           else
           {
               /* 在控制终端显示收到的数据 */
H
hduffddybz 已提交
126
               rt_kprintf("RECEIVED DATA = %s \n" , recv_data);
B
Bernard Xiong 已提交
127 128 129 130 131
           }
       }
   }

   /* 退出服务 */
132
   closesocket(sock);
B
Bernard Xiong 已提交
133 134 135 136 137 138 139 140 141 142 143 144

   /* 释放接收缓冲 */
   rt_free(recv_data);

   return ;
}

#ifdef RT_USING_FINSH
#include <finsh.h>
/* 输出tcpserv函数到finsh shell中 */
FINSH_FUNCTION_EXPORT(tcpserv, startup tcp server);
#endif