当前位置:网站首页>LwIP learning socket (application)
LwIP learning socket (application)
2022-07-03 07:48:00 【Seven demons 71】
Single connection TCP/IP signal communication
Client and server flowchart
Its flow chart is like making a customer service call , The server can be understood as the customer service phone of China Mobile , We are the client .
The server needs to use Socket()
Register a phone , Use bind()
Bind a phone number 10086,listen()
It's a customer service listening to the phone . Then enter accept()
Blocked . After all, at this time, no one calls and there is no need to deal with anything .
At this time, our client can also use socket()
Register a phone , And then use connect()
call 10086.
The customer service, who was originally idle, heard the jingling phone ring , It will start from accept()
The blocking state of jumps out , There will be a famous TCP Three handshake . after “ feed ~” “ feed ?” “ feed ~” after , You can complain about why you gave me a set meal fee barabarabara ……. then 10086 Give his explanation .
Client side usage close()
The function hung up angrily . adopt Four waves after ,10086 Also used close()
Hung up the phone .
The code analysis :
If the basic used in the above flow chart socket API If you don't understand, you can read another article of mine 《Socket API piece 》
Here the code uses wildfire 《LwIP Application development practice guide 》 The routine in .
The server
#include "tcpecho.h"
#include "lwip/opt.h"
#if LWIP_SOCKET
#include <lwip/sockets.h>
#include "lwip/sys.h"
#include "lwip/api.h"
/*--------------------------------------------------------------------*/
#define PORT 5001
#define RECV_DATA (1024)
static void
tcpecho_thread(void *arg)
{
int sock = -1,connected;
char *recv_data;
struct sockaddr_in server_addr,client_addr;
socklen_t sin_size;
int recv_data_len;
recv_data = (char *)pvPortMalloc(RECV_DATA); // apply 1024 Byte memory , As a storage area for receiving data
if (recv_data == NULL)
{
printf("No memory\n"); // If the application fails, jump to __exit
goto __exit;
}
sock = socket(AF_INET, SOCK_STREAM, 0); // Create a socket Socket sock
if (sock < 0)
{
printf("Socket error\n"); // Failed to create, jump to __exit
goto __exit;
}
server_addr.sin_family = AF_INET; // choice IPV4 Protocol family
server_addr.sin_addr.s_addr = INADDR_ANY;// Allow any address links
server_addr.sin_port = htons(PORT); // Set the port number 5001
memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)// Use bind() Information configured before binding
{
printf("Unable to bind\n");
goto __exit;
}
if (listen(sock, 5) == -1)//sock Monitor at most 5 A link
{
printf("Listen error\n");
goto __exit;
}
while (1)
{
sin_size = sizeof(struct sockaddr_in);
connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size);// Blocking waiting client Links , If there is no link, the task will enter a blocking state here .
printf("new client connected from (%s, %d)\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));// Print the address and port information of the client
{
int flag = 1;
setsockopt(connected,
IPPROTO_TCP, /* set option at TCP level */
TCP_NODELAY, /* name of option */
(void *) &flag, /* the cast is historical cruft */
sizeof(int)); /* length of option value */
}
while (1)
{
recv_data_len = recv(connected, recv_data, RECV_DATA, 0);
// After the client connects, it will block here , Waiting to receive data
if (recv_data_len <= 0)
// If the client disconnects , The client sends FIN package ,recv() Returns the -1, Get out of this while Loop back to accept() Blocking
break;
printf("recv %d len data\n",recv_data_len);
write(connected,recv_data,recv_data_len);// Writing data
}
if (connected >= 0)
closesocket(connected);// If there was a customer connection before , The client connection will be closed
connected = -1;
}
__exit:
if (sock >= 0) closesocket(sock);// The server socket Create success , Then shut down the server socket
if (recv_data) free(recv_data);// If the memory request is received successfully , Then release the receiving memory
}
void
tcpecho_init(void)
{
sys_thread_new("tcpecho_thread", tcpecho_thread, NULL, 512, 4);
}
client
#include "client.h"
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/api.h"
#include <lwip/sockets.h>
#define PORT 5001
#define IP_ADDR "192.168.0.181"
static void client(void *thread_param)
{
int sock = -1;
struct sockaddr_in client_addr;
uint8_t send_buf[]= "This is a TCP Client test...\n";
while (1)
{
sock = socket(AF_INET, SOCK_STREAM, 0);// Create a client socket It's called sock
if (sock < 0)
{
// If creation fails, delay 10ms Continue to create
printf("Socket error\n");
vTaskDelay(10);
continue;
}
client_addr.sin_family = AF_INET;// Address protocol family set by the server IPV4
client_addr.sin_port = htons(PORT);// The port number set by the server
client_addr.sin_addr.s_addr = inet_addr(IP_ADDR);// The address of the server
memset(&(client_addr.sin_zero), 0, sizeof(client_addr.sin_zero));
if (connect(sock,
(struct sockaddr *)&client_addr,
sizeof(struct sockaddr)) == -1)// Connect to server
{
// If the connection fails, close socket() Time delay 10ms Jump out of while(1)
printf("Connect failed!\n");
closesocket(sock);
vTaskDelay(10);
continue;
}
printf("Connect to iperf server successful!\n");
while (1)
{
if (write(sock,send_buf,sizeof(send_buf)) < 0)// Writing data
break;
vTaskDelay(1000);
}
closesocket(sock);// Close socket
}
}
void
client_init(void)
{
sys_thread_new("client", client, NULL, 512, 4);
}
deficiencies :
The above is provided by wildfire socket The usage of is Duplicate server , Only one connection can be processed at a time . When other clients use connect()
After the connection , If the client does not close()
, Then the server will be blocked in recv() At function . The correct client connection will not be responded by the server .
Solutions :
Use select()
function . stay recv()
Before using select()
First check whether the correct connection arrives .select()
The return value of the function
- When the corresponding set of file descriptors monitored meets the conditions , For example, when there is data in the read file descriptor set , kernel (I/O) Repair according to the state Change file descriptor set , And return a greater than 0 Number of numbers .
- When there is no file descriptor that meets the conditions , And set timeval Monitoring time out ,select The function returns a value of 0 Value .
- When select When a negative value is returned , An error occurred .
Now? FD Add clients to the queue that need to be monitored , Such as keys and com port .
Example reference :
FD_ZERO(&rds);
FD_SET(button_fd,&rds); // Add keys fd
FD_SET(com,&rds)// add to com fd
ret=select(fd+1,&rds,NULL,NULL,NULL);
if(ret<0)
{
printf("select failure\n");
exit(1);
}
if(ret==0)
{
printf("select timeout\n");
}
else if(FD_ISSET(button_fd,&rds)) // Key client connection
{
read(button_fd,&but_status,sizeof(but_status));
}
else if(FD_ISSET(com_fd,&rds)) //com Client connection
{
read(.......);
}
reference :
《LwIP Application development practice guide 》
qicheng777 The blog of
边栏推荐
- Analysis of the ninth Blue Bridge Cup single chip microcomputer provincial competition
- Technical dry goods | hundred lines of code to write Bert, Shengsi mindspire ability reward
- Es writing fragment process
- HDMI2.1与HDMI2.0的区别以及转换PD信号。
- Go language foundation ------ 14 ------ gotest
- Epoll related references
- 【MySQL 14】使用DBeaver工具远程备份及恢复MySQL数据库(Linux 环境)
- Technology dry goods | luxe model for the migration of mindspore NLP model -- reading comprehension task
- 项目经验分享:实现一个昇思MindSpore 图层 IR 融合优化 pass
- Go language foundation ----- 09 ----- exception handling (error, panic, recover)
猜你喜欢
HDMI2.1与HDMI2.0的区别以及转换PD信号。
Pat class a 1028 list sorting
技术干货 | AlphaFold/ RoseTTAFold开源复现(2)—AlphaFold流程分析和训练构建
【MySQL 14】使用DBeaver工具远程备份及恢复MySQL数据库(Linux 环境)
技术干货|昇思MindSpore NLP模型迁移之Bert模型—文本匹配任务(二):训练和评估
Go language foundation ----- 18 ----- collaboration security, mutex lock, read-write lock, anonymous lock, sync Once
Robots protocol
【LeetCode】4. Best Time to Buy and Sell Stock·股票买卖最佳时机
Lucene skip table
Pat class a 1032 sharing
随机推荐
技术干货|昇思MindSpore创新模型EPP-MVSNet-高精高效的三维重建
一篇文章让你读懂-曼彻斯特编码
Huawei switch basic configuration (telnet/ssh login)
[MySQL 13] if you change your password for the first time after installing mysql, you can skip MySQL password verification to log in
[MySQL 11] how to solve the case sensitive problem of MySQL 8.0.18
PAT甲级 1030 Travel Plan
An overview of IfM Engage
Redis查看客户端连接
Iterm2设置
[MySQL 14] use dbeaver tool to remotely backup and restore MySQL database (Linux Environment)
OSPF protocol summary
Go language foundation ------ 12 ------ JSON
项目经验分享:基于昇思MindSpore实现手写汉字识别
Go language foundation ----- 03 ----- process control, function, value transfer, reference transfer, defer function
Pat grade a 1029 median
GoLang之结构体
Lucene introduces NFA
密西根大学张阳教授受聘中国上海交通大学客座教授(图)
技术干货|昇思MindSpore NLP模型迁移之LUKE模型——阅读理解任务
研究显示乳腺癌细胞更容易在患者睡觉时进入血液