diff --git a/9_tcp_server_client/Makefile b/9_tcp_server_client/Makefile new file mode 100644 index 0000000..03fb855 --- /dev/null +++ b/9_tcp_server_client/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := tcp_perf + +include $(IDF_PATH)/make/project.mk + diff --git a/9_tcp_server_client/README.md b/9_tcp_server_client/README.md new file mode 100644 index 0000000..408536d --- /dev/null +++ b/9_tcp_server_client/README.md @@ -0,0 +1 @@ + - esp as a tcp server or client \ No newline at end of file diff --git a/9_tcp_server_client/main/Kconfig.projbuild b/9_tcp_server_client/main/Kconfig.projbuild new file mode 100644 index 0000000..7c95b49 --- /dev/null +++ b/9_tcp_server_client/main/Kconfig.projbuild @@ -0,0 +1,119 @@ +menu "Example Configuration" + +#choice +# prompt "TCP_PERF_MODE " +# default MODE_TCP_SHIELDBOX +# help +# This option set performance mode. +# +# - Testing in shieldbox for "Performance in shieldbox" setting. +# +# - Testing in air for "Performance in air" setting. +# +# - Testing in long distance for "Performance in long distance" setting. +# +# +#config MODE_TCP_SHIELDBOX +# bool "Performance in shieldbox" +#config MODE_TCP_AIR +# bool "Performance in air" +#config MODE_TCP_LONG_DISTANCE +# bool "Performance in long distance" +#endchoice + +choice TCP_PERF_WIFI_MODE + prompt "AP or STA" + default TCP_PERF_ESP_IS_STATION + help + Whether the esp32 is softAP or station. + +config TCP_PERF_ESP_IS_SOFTAP + bool "SoftAP" +config TCP_PERF_ESP_IS_STATION + bool "Station" +endchoice + +config TCP_PERF_WIFI_MODE_AP + bool + default y if TCP_PERF_ESP_IS_SOFTAP + default n if TCP_PERF_ESP_IS_STATION + +choice TCP_PERF_SERVER_CLIENT + prompt "server or client" + default TCP_PERF_ESP_IS_CLIENT + help + Whether the esp32 is tcp server or client. + + We suggest to choose "client" if you choose "station" in "wifi mode". + +config TCP_PERF_ESP_IS_SERVER + bool "server" +config TCP_PERF_ESP_IS_CLIENT + bool "client" +endchoice + +config TCP_PERF_SERVER + bool + default y if TCP_PERF_ESP_IS_SERVER + default n if TCP_PERF_ESP_IS_CLIENT + +choice TCP_PERF_TX_RX + prompt "send or receive" + default TCP_PERF_ESP_RECV + help + Whether the esp32 will send or receive. + +config TCP_PERF_ESP_SEND + bool "send" +config TCP_PERF_ESP_RECV + bool "receive" +endchoice + +config TCP_PERF_TX + bool + default y if TCP_PERF_ESP_SEND + default n if TCP_PERF_ESP_RECV + +config TCP_PERF_DELAY_DEBUG + bool "TCP performance delay info enable" + depends on TCP_PERF_TX + default n + help + Show TCP performance delay info. + + Ignore in TCP RX. + +config TCP_PERF_WIFI_SSID + string "WiFi SSID" + default "esp_wifi_test1" + help + SSID (network name) for the example to connect to. + +config TCP_PERF_WIFI_PASSWORD + string "WiFi Password" + default "1234567890" + help + WiFi password (WPA or WPA2) for the example to use. + +config TCP_PERF_SERVER_PORT + int "TCP server port" + default 4567 + help + Which will the tcp server use. + +config TCP_PERF_SERVER_IP + string "TCP server ip" + depends on TCP_PERF_ESP_IS_CLIENT + default "192.168.4.1" + help + IP of TCP server. + + Ignore in TCP server. + +config TCP_PERF_PKT_SIZE + int "Size of TCP packet" + default 1460 + help + the data send&recv packet size. + +endmenu diff --git a/9_tcp_server_client/main/component.mk b/9_tcp_server_client/main/component.mk new file mode 100644 index 0000000..61f8990 --- /dev/null +++ b/9_tcp_server_client/main/component.mk @@ -0,0 +1,8 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# diff --git a/9_tcp_server_client/main/tcp_main.c b/9_tcp_server_client/main/tcp_main.c new file mode 100644 index 0000000..fca2a43 --- /dev/null +++ b/9_tcp_server_client/main/tcp_main.c @@ -0,0 +1,135 @@ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_log.h" +#include "esp_err.h" +#include "nvs_flash.h" +#include "xuhong_Tcp.h" + +//this task establish a TCP connection and receive data from TCP +static void tcp_conn(void *pvParameters) +{ + while (1) + { + + g_rxtx_need_restart = false; + + ESP_LOGI(TAG, "task tcp_conn..."); + + /*wating for connecting to AP*/ + xEventGroupWaitBits(tcp_event_group, WIFI_CONNECTED_BIT, false, true, portMAX_DELAY); + TaskHandle_t tx_rx_task = NULL; + +#if TCP_SERVER_CLIENT_OPTION + + ESP_LOGI(TAG, "tcp_server will start after 3s..."); + vTaskDelay(3000 / portTICK_RATE_MS); + ESP_LOGI(TAG, "create_tcp_server."); + int socket_ret = create_tcp_server(true); +#else + ESP_LOGI(TAG, "tcp_client will start after 3s..."); + vTaskDelay(3000 / portTICK_RATE_MS); + ESP_LOGI(TAG, "create_tcp_Client."); + int socket_ret = create_tcp_client(); +#endif + if (socket_ret == ESP_FAIL) + { + ESP_LOGI(TAG, "create tcp socket error,stop..."); + continue; + } + else + { + ESP_LOGI(TAG, "create tcp socket succeed..."); + } + + if (pdPASS != xTaskCreate(&recv_data, "recv_data", 4096, NULL, 4, &tx_rx_task)) + { + ESP_LOGI(TAG, "Recv task create fail!"); + } + else + { + ESP_LOGI(TAG, "Recv task create succeed!"); + } + + double bps; + + while (1) + { + + vTaskDelay(3000 / portTICK_RATE_MS); + +#if TCP_SERVER_CLIENT_OPTION + + if (g_rxtx_need_restart) + { + ESP_LOGE(TAG, "tcp server send or receive task encoutner error, need to restart..."); + + if (ESP_FAIL != create_tcp_server(false)) + { + if (pdPASS != xTaskCreate(&recv_data, "recv_data", 4096, NULL, 4, &tx_rx_task)) + { + ESP_LOGE(TAG, "tcp server Recv task create fail!"); + } + else + { + ESP_LOGE(TAG, "tcp server Recv task create succeed!"); + } + } + } +#else + if (g_rxtx_need_restart) + { + ESP_LOGI(TAG, "tcp_client will reStart after 3s..."); + vTaskDelay(3000 / portTICK_RATE_MS); + ESP_LOGI(TAG, "create_tcp_Client..."); + int socket_ret = create_tcp_client(); + + if (socket_ret == ESP_FAIL) + { + ESP_LOGE(TAG, "create tcp socket error,stop..."); + continue; + } + else + { + ESP_LOGI(TAG, "create tcp socket succeed..."); + g_rxtx_need_restart = false; + } + + if (pdPASS != xTaskCreate(&recv_data, "recv_data", 4096, NULL, 4, &tx_rx_task)) + { + ESP_LOGE(TAG, "Recv task create fail!"); + } + else + { + ESP_LOGI(TAG, "Recv task create succeed!"); + } + } +#endif + } + } + + vTaskDelete(NULL); +} + +void app_main(void) +{ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES) + { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + +#if TCP_SERVER_CLIENT_OPTION + ESP_LOGI(TAG, "As a Tcp Server , will start wifi_init_softap..."); + wifi_init_softap(); +#else + + ESP_LOGI(TAG, "As a Tcp Client , will start wifi_init_sta..."); + wifi_init_sta(); +#endif + xTaskCreate(&tcp_conn, "tcp_conn", 4096, NULL, 5, NULL); +} diff --git a/9_tcp_server_client/main/xuhong_Tcp.c b/9_tcp_server_client/main/xuhong_Tcp.c new file mode 100644 index 0000000..6883a6f --- /dev/null +++ b/9_tcp_server_client/main/xuhong_Tcp.c @@ -0,0 +1,379 @@ +/* tcp_perf Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" + +#include "xuhong_Tcp.h" + +/* FreeRTOS event group to signal when we are connected to wifi */ +EventGroupHandle_t tcp_event_group; + +/*socket*/ +static int server_socket = 0; +static struct sockaddr_in server_addr; +static struct sockaddr_in client_addr; +static unsigned int socklen = sizeof(client_addr); +static int connect_socket = 0; +bool g_rxtx_need_restart = false; + +int g_total_data = 0; + +#if EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO + +int g_total_pack = 0; +int g_send_success = 0; +int g_send_fail = 0; +int g_delay_classify[5] = {0}; + +#endif /*EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO*/ + +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + switch (event->event_id) + { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + esp_wifi_connect(); + xEventGroupClearBits(tcp_event_group, WIFI_CONNECTED_BIT); + break; + case SYSTEM_EVENT_STA_CONNECTED: + xEventGroupSetBits(tcp_event_group, WIFI_CONNECTED_BIT); + break; + case SYSTEM_EVENT_STA_GOT_IP: + ESP_LOGI(TAG, "got ip:%s\n", + ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); + xEventGroupSetBits(tcp_event_group, WIFI_CONNECTED_BIT); + break; + case SYSTEM_EVENT_AP_STACONNECTED: + ESP_LOGI(TAG, "station:" MACSTR " join,AID=%d\n", + MAC2STR(event->event_info.sta_connected.mac), + event->event_info.sta_connected.aid); + xEventGroupSetBits(tcp_event_group, WIFI_CONNECTED_BIT); + break; + case SYSTEM_EVENT_AP_STADISCONNECTED: + ESP_LOGI(TAG, "station:" MACSTR "leave,AID=%d\n", + MAC2STR(event->event_info.sta_disconnected.mac), + event->event_info.sta_disconnected.aid); + g_rxtx_need_restart = true; + xEventGroupClearBits(tcp_event_group, WIFI_CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} + +//send data +void send_data(void *pvParameters) +{ + int len = 0; + char *databuff = (char *)malloc(EXAMPLE_DEFAULT_PKTSIZE * sizeof(char)); + memset(databuff, EXAMPLE_PACK_BYTE_IS, EXAMPLE_DEFAULT_PKTSIZE); + vTaskDelay(100 / portTICK_RATE_MS); + ESP_LOGI(TAG, "start sending..."); + + while (1) + { + int to_write = EXAMPLE_DEFAULT_PKTSIZE; + + while (to_write > 0) + { + len = send(connect_socket, databuff + (EXAMPLE_DEFAULT_PKTSIZE - to_write), to_write, 0); + if (len > 0) + { + g_total_data += len; + to_write -= len; + } + else + { + int err = get_socket_error_code(connect_socket); + + if (err != ENOMEM) + { + show_socket_error_reason("send_data", connect_socket); + break; + } + } + } + +#if EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO + gettimeofday(&tv_finish, NULL); +#endif /*EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO*/ + if (g_total_data > 0) + { +#if EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO + g_send_success++; + send_delay_ms = (tv_finish.tv_sec - tv_start.tv_sec) * 1000 + (tv_finish.tv_usec - tv_start.tv_usec) / 1000; + if (send_delay_ms < 30) + { + g_delay_classify[0]++; + } + else if (send_delay_ms < 100) + { + g_delay_classify[1]++; + } + else if (send_delay_ms < 300) + { + g_delay_classify[2]++; + } + else if (send_delay_ms < 1000) + { + g_delay_classify[3]++; + } + else + { + g_delay_classify[4]++; + } +#endif /*EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO*/ + } + else + { + break; + } + } + g_rxtx_need_restart = true; + free(databuff); + vTaskDelete(NULL); +} + +//receive data +void recv_data(void *pvParameters) +{ + int len = 0; + + char databuff[1024]; + + while (1) + { + //每次接收都要清空接收数组 + memset(databuff, 0x00, sizeof(databuff)); + len = recv(connect_socket, databuff, sizeof(databuff), 0); + g_rxtx_need_restart = false; + if (len > 0) + { + g_total_data += len; + //打印接收到的数组 + ESP_LOGI(TAG, "recvData: %s\n", databuff); + //原路返回,不指定某个客户端 + send(connect_socket, databuff, sizeof(databuff), 0); + //sendto(connect_socket, databuff , sizeof(databuff), 0, (struct sockaddr *) &remote_addr,sizeof(remote_addr)); + } + else + { + show_socket_error_reason("recv_data", connect_socket); + g_rxtx_need_restart = true; +#if !TCP_SERVER_CLIENT_OPTION + break; +#endif + } + } + + close_socket(); + g_rxtx_need_restart = true; + vTaskDelete(NULL); +} + +esp_err_t create_tcp_server(bool isCreatServer) +{ + + if (isCreatServer) + { + ESP_LOGI(TAG, "server socket....,port=%d", TCP_PORT); + server_socket = socket(AF_INET, SOCK_STREAM, 0); + + if (server_socket < 0) + { + show_socket_error_reason("create_server", server_socket); + return ESP_FAIL; + } + + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(TCP_PORT); + server_addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) + { + show_socket_error_reason("bind_server", server_socket); + close(server_socket); + return ESP_FAIL; + } + } + + if (listen(server_socket, 5) < 0) + { + show_socket_error_reason("listen_server", server_socket); + close(server_socket); + return ESP_FAIL; + } + + connect_socket = accept(server_socket, (struct sockaddr *)&client_addr, &socklen); + + if (connect_socket < 0) + { + show_socket_error_reason("accept_server", connect_socket); + close(server_socket); + return ESP_FAIL; + } + + /*connection established,now can send/recv*/ + ESP_LOGI(TAG, "tcp connection established!"); + return ESP_OK; +} + +//创建TCP客户端连接到指定的服务器 +esp_err_t create_tcp_client() +{ + + ESP_LOGI(TAG, "will connect gateway ssid : %s port:%d\n", + TCP_SERVER_ADRESS, TCP_PORT); + + connect_socket = socket(AF_INET, SOCK_STREAM, 0); + + if (connect_socket < 0) + { + show_socket_error_reason("create client", connect_socket); + return ESP_FAIL; + } + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(TCP_PORT); + server_addr.sin_addr.s_addr = inet_addr(TCP_SERVER_ADRESS); + ESP_LOGI(TAG, "connectting server..."); + if (connect(connect_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) + { + show_socket_error_reason("client connect", connect_socket); + ESP_LOGE(TAG, "connect failed!"); + return ESP_FAIL; + } + ESP_LOGI(TAG, "connect success!"); + return ESP_OK; +} + +//wifi_init_sta +void wifi_init_sta() +{ + tcp_event_group = xEventGroupCreate(); + + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + wifi_config_t wifi_config = { + .sta = { + .ssid = GATEWAY_SSID, + .password = GATEWAY_PAS}, + }; + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + + ESP_LOGI(TAG, "wifi_init_sta finished."); + ESP_LOGI(TAG, "connect to ap SSID:%s password:%s \n", + GATEWAY_SSID, GATEWAY_PAS); +} + +//wifi_init_softap +void wifi_init_softap() +{ + tcp_event_group = xEventGroupCreate(); + + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + wifi_config_t wifi_config = { + .ap = { + .ssid = SOFT_AP_SSID, + .ssid_len = 0, + .max_connection = SOFT_AP_MAX_CONNECT, + .password = SOFT_AP_PAS, + .authmode = WIFI_AUTH_WPA_WPA2_PSK}, + }; + if (strlen(EXAMPLE_DEFAULT_PWD) == 0) + { + wifi_config.ap.authmode = WIFI_AUTH_OPEN; + } + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP)); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + + ESP_LOGI(TAG, "SoftAP set finish:%s pas:%s \n", + EXAMPLE_DEFAULT_SSID, EXAMPLE_DEFAULT_PWD); +} + +int get_socket_error_code(int socket) +{ + int result; + u32_t optlen = sizeof(int); + int err = getsockopt(socket, SOL_SOCKET, SO_ERROR, &result, &optlen); + if (err == -1) + { + ESP_LOGE(TAG, "getsockopt failed:%s", strerror(err)); + return -1; + } + return result; +} + +int show_socket_error_reason(const char *str, int socket) +{ + int err = get_socket_error_code(socket); + + if (err != 0) + { + ESP_LOGW(TAG, "%s socket error %d %s", str, err, strerror(err)); + } + + return err; +} + +int check_working_socket() +{ + int ret; +#if EXAMPLE_ESP_TCP_MODE_SERVER + ESP_LOGD(TAG, "check server_socket"); + ret = get_socket_error_code(server_socket); + if (ret != 0) + { + ESP_LOGW(TAG, "server socket error %d %s", ret, strerror(ret)); + } + if (ret == ECONNRESET) + { + return ret; + } +#endif + ESP_LOGD(TAG, "check connect_socket"); + ret = get_socket_error_code(connect_socket); + if (ret != 0) + { + ESP_LOGW(TAG, "connect socket error %d %s", ret, strerror(ret)); + } + if (ret != 0) + { + return ret; + } + return 0; +} + +void close_socket() +{ + close(connect_socket); + close(server_socket); +} diff --git a/9_tcp_server_client/main/xuhong_Tcp.h b/9_tcp_server_client/main/xuhong_Tcp.h new file mode 100644 index 0000000..77ca563 --- /dev/null +++ b/9_tcp_server_client/main/xuhong_Tcp.h @@ -0,0 +1,121 @@ + +#ifndef __TCP_PERF_H__ +#define __TCP_PERF_H__ + + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*test options*/ +#define EXAMPLE_ESP_WIFI_MODE_AP CONFIG_TCP_PERF_WIFI_MODE_AP +#define EXAMPLE_ESP_TCP_MODE_SERVER CONFIG_TCP_PERF_SERVER +#define EXAMPLE_ESP_TCP_PERF_TX CONFIG_TCP_PERF_TX +#define EXAMPLE_ESP_TCP_DELAY_INFO CONFIG_TCP_PERF_DELAY_DEBUG + +/*AP info and tcp_server info*/ +#define EXAMPLE_DEFAULT_SSID CONFIG_TCP_PERF_WIFI_SSID +#define EXAMPLE_DEFAULT_PWD CONFIG_TCP_PERF_WIFI_PASSWORD +#define EXAMPLE_DEFAULT_PORT CONFIG_TCP_PERF_SERVER_PORT +#define EXAMPLE_DEFAULT_PKTSIZE CONFIG_TCP_PERF_PKT_SIZE +#define EXAMPLE_MAX_STA_CONN 1 + +#ifdef CONFIG_TCP_PERF_SERVER_IP +#define EXAMPLE_DEFAULT_SERVER_IP CONFIG_TCP_PERF_SERVER_IP +#else +#define EXAMPLE_DEFAULT_SERVER_IP "192.168.4.1" +#endif +#define EXAMPLE_PACK_BYTE_IS 97 //'a' + + + + + +#define TCP_SERVER_CLIENT_OPTION FALSE //true为开启热点并且创建tcp服务器,fasle为连接到指定的路由器并且连接到指定的tcp服务器 +#define TAG "XuHongTCP-->" //打印的tag + +//以下是softAP热点模式的配置信息 +#define SOFT_AP_SSID "XuHongTCP2018" + +#define SOFT_AP_PAS "xuhong123456" //如果密码设置为空,则配置的热点是开放的,没有密码的。 + +#define SOFT_AP_MAX_CONNECT 1 //作为AP热点时候,最大的连接数目 + + +//以下是station模式配置信息,是您家里的路由器的信息 + +#define GATEWAY_SSID "AliyunOnlyTest" + +#define GATEWAY_PAS "aliyun#123456" + +#define TCP_SERVER_ADRESS "192.168.1.104" //要连接TCP服务器地址 + + +//统一的端口号,包括TCP客户端或者服务端 +#define TCP_PORT 8266 + + + + + + + + + + + + + + +/* FreeRTOS event group to signal when we are connected to wifi*/ +extern EventGroupHandle_t tcp_event_group; +#define WIFI_CONNECTED_BIT BIT0 + +extern int g_total_data; +extern bool g_rxtx_need_restart; + +#if EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO +extern int g_total_pack; +extern int g_send_success; +extern int g_send_fail; +extern int g_delay_classify[5]; +#endif/*EXAMPLE_ESP_TCP_PERF_TX && EXAMPLE_ESP_TCP_DELAY_INFO*/ + + +//using esp as station +void wifi_init_sta(); +//using esp as softap +void wifi_init_softap(); + +//create a tcp server socket. return ESP_OK:success ESP_FAIL:error +esp_err_t create_tcp_server(bool isCreatServer); +//create a tcp client socket. return ESP_OK:success ESP_FAIL:error +esp_err_t create_tcp_client(); + +//send data task +void send_data(void *pvParameters); +//receive data task +void recv_data(void *pvParameters); + +//close all socket +void close_socket(); + +//get socket error code. return: error code +int get_socket_error_code(int socket); + +//show socket error code. return: error code +int show_socket_error_reason(const char* str, int socket); + +//check working socket +int check_working_socket(); + + +#ifdef __cplusplus +} +#endif + + +#endif /*#ifndef __TCP_PERF_H__*/ +