介绍

C Liunx实现EchoServer非阻塞客户端(TPC协议)

支持库

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdbool.h>

代码

typedef struct EchoClientInfo
{
    int socketFD;
    struct sockaddr_in serverAddr;
    int bufferSize;
    struct timeval timeout;
    bool block;
 
} EchoClient;
 
EchoClient *InitClient();
 
int ConnectServer(EchoClient *client, char *ip, int port, bool noBlock);
 
int SendServerDate(EchoClient *client, char *date);
 
char *GetServerDate(EchoClient *client);
 
void CloseConnect(EchoClient *client);
 
void SetClientTimeout(EchoClient *client, int s, int us);
 
void FreeClient(EchoClient *client);
 
EchoClient *InitClient()
{
    EchoClient *result = (EchoClient *)malloc(sizeof(EchoClient));
    if (result != NULL)
    {
        memset(result, 0, sizeof(EchoClient));
        result->socketFD = 0;
        result->bufferSize = 1024;
        SetClientTimeout(result, 3, 0);
    }
    return result;
 
    return result;
}
 
int ConnectServer(EchoClient *client, char *ip, int port, bool noBlock)
{
    struct timeval timeout = client->timeout;
    int nRet,ret;
 
    client->socketFD = socket(AF_INET, SOCK_STREAM, 0);
    if (client->socketFD < 0)
        return -2;
    if (noBlock)
    {
        int flags = fcntl(client->socketFD, F_GETFL, 0);
        fcntl(client->socketFD, F_SETFL, flags | O_NONBLOCK);
    }
    client->block = !noBlock;
 
    client->serverAddr.sin_family = AF_INET;
    inet_pton(AF_INET, ip, &client->serverAddr.sin_addr);
    client->serverAddr.sin_port = htons(port);
 
    ret = connect(client->socketFD, (struct sockaddr *)&client->serverAddr, sizeof(client->serverAddr));
 
    if (client->block && ret == 0)
        goto Success;
 
    fd_set wait;
    FD_ZERO(&wait);
    FD_SET(client->socketFD, &wait);
 
    nRet = select(client->socketFD + 1, NULL, &wait, NULL, &timeout);
 
    if (nRet == 0)
        return -1;
    else if (nRet < 0)
        return -2;
 
Success:
    return 0;
}
 
char *GetServerDate(EchoClient *client)
{
    int len, ready, size = 1;
    char *temp;
    char *result = (char *)malloc(sizeof(char));
    char *buffer = (char *)malloc(sizeof(char) * client->bufferSize);
    if (!result)
        return "";
    else
        result[0] = '\0';
 
    if (!buffer)
        return "";
    else
        buffer[0] = '\0';
 
    struct timeval timeout = client->timeout;
    fd_set wait;
    FD_ZERO(&wait);
    FD_SET(client->socketFD, &wait);
 
    while (true)
    {
        if (client->block)
            goto ReadMessage;
        ready = select(client->socketFD + 1, &wait, NULL, NULL, &timeout);
        if (ready > 0)
        {
            if (FD_ISSET(client->socketFD, &wait))
            {
            ReadMessage:
                len = read(client->socketFD, buffer, client->bufferSize - 1);
                if (len > 0)
                {
                    size += len;
                    buffer[len] = '\0';
                    temp = (char *)realloc(result, sizeof(char) * size);
                    if (!temp)
                        break;
                    strcpy(temp, result);
                    result = temp;
                    strcat(result, buffer);
                    if (client->block)
                        continue;
                }
                else
                    break;
            }
        }
        else
            break;
    }
    return result;
}
 
int SendServerDate(EchoClient *client, char *date)
{
    return write(client->socketFD, date, strlen(date));
}
 
void CloseConnect(EchoClient *client)
{
    if (client->socketFD)
        close(client->socketFD);
}
 
void SetClientTimeout(EchoClient *client, int s, int us)
{
    client->timeout.tv_sec = s;
    client->timeout.tv_usec = us;
}
 
void FreeClient(EchoClient *client){
    free(client);
}

示例

假设服务端地址:192.168.2.2 | 端口是1001

#include <stdio.h>
 
int main()
{
    EchoClient *client = InitClient();
    SetClientTimeout(client,10,0);
    char *message, ret, con;
    while (true)
    {
        printf("尝试连接");
        con = ConnectServer(client, "192.168.2.2", 1001, true);
        if (con == 0)
        {
            ret = SendServerDate(client, "hello");
            if (ret > 0)
            {
                message = GetServerDate(client);
                printf("-->来自服务端的消息:%s", message);
            }
        }
        CloseConnect(client);
        printf("\n");
    }
}