C语言利用UCOSII和LWIP的SOCKET套接字编写3个不同任务的客户端代码,要求:①无论服务端先开启还是客户端先开启,都可以连接并且无延迟;②客户端开启一段时间后,服务端再开启,3个客户端必须在短时间内都要和服务端连接上;③需要保活机制
时间: 2023-11-06 21:05:40 浏览: 91
以下是基于UCOSII和LWIP的SOCKET套接字编写的示例代码,实现3个不同任务的客户端连接服务端,并具有保活机制。
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "includes.h"
#include "lwip/sockets.h"
#include "lwip/inet.h"
#include "lwip/netdb.h"
#include "lwip/tcp.h"
#define SERVER_PORT 8080
#define SERVER_ADDR "192.168.1.100"
#define KEEP_ALIVE_TIME 30
static void task_client1(void* p);
static void task_client2(void* p);
static void task_client3(void* p);
void keep_alive(int socketfd)
{
int keepAlive = 1; // 开启keepalive属性
int keepIdle = KEEP_ALIVE_TIME; // 开启keepalive后,首次探测开始前的TCP空闭时间
int keepInterval = 5; // 开启keepalive后,两次探测之间的时间间隔
int keepCount = 3; // 开启keepalive后,探测次数,超过该次数后认定为断开连接
setsockopt(socketfd, SOL_SOCKET, SO_KEEPALIVE, (void*)&keepAlive, sizeof(keepAlive));
setsockopt(socketfd, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));
setsockopt(socketfd, SOL_TCP, TCP_KEEPINTVL, (void*)&keepInterval, sizeof(keepInterval));
setsockopt(socketfd, SOL_TCP, TCP_KEEPCNT, (void*)&keepCount, sizeof(keepCount));
}
int main()
{
OSInit();
OSTaskCreate(task_client1, NULL, 2048, 5);
OSTaskCreate(task_client2, NULL, 2048, 6);
OSTaskCreate(task_client3, NULL, 2048, 7);
OSStart();
return 0;
}
static void task_client1(void* p)
{
int socketfd;
struct sockaddr_in server_addr;
while (1) {
// 创建套接字
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd == -1) {
printf("socket create error\n");
vTaskDelay(1000);
continue;
}
// 填写服务器地址信息
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_ADDR);
// 连接服务器
if (connect(socketfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
printf("connect server error\n");
close(socketfd);
vTaskDelay(1000);
continue;
}
printf("client1 connect server success\n");
// 保活机制
keep_alive(socketfd);
// 其他任务处理
while (1) {
vTaskDelay(1000);
}
}
}
static void task_client2(void* p)
{
int socketfd;
struct sockaddr_in server_addr;
while (1) {
// 创建套接字
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd == -1) {
printf("socket create error\n");
vTaskDelay(1000);
continue;
}
// 填写服务器地址信息
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_ADDR);
// 连接服务器
if (connect(socketfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
printf("connect server error\n");
close(socketfd);
vTaskDelay(1000);
continue;
}
printf("client2 connect server success\n");
// 保活机制
keep_alive(socketfd);
// 其他任务处理
while (1) {
vTaskDelay(1000);
}
}
}
static void task_client3(void* p)
{
int socketfd;
struct sockaddr_in server_addr;
while (1) {
// 创建套接字
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd == -1) {
printf("socket create error\n");
vTaskDelay(1000);
continue;
}
// 填写服务器地址信息
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_ADDR);
// 连接服务器
if (connect(socketfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
printf("connect server error\n");
close(socketfd);
vTaskDelay(1000);
continue;
}
printf("client3 connect server success\n");
// 保活机制
keep_alive(socketfd);
// 其他任务处理
while (1) {
vTaskDelay(1000);
}
}
}
```
在示例代码中,我们创建了3个不同的任务,分别是`task_client1`,`task_client2`和`task_client3`。任务中通过套接字连接服务器,并设置保活机制。其中,保活时间设置为30秒,即超过30秒没有数据传输,就会向服务器发送探测包保持连接。
在`main`函数中,我们使用`OSInit`初始化操作系统,创建3个任务,并使用`OSStart`启动操作系统。
阅读全文