c - C 中两个服务器的套接字客户端

标签 c sockets client

在我的 C 程序中,我需要与两台服务器通信,一台位于 IP=X1 PORT=X2,另一台服务器位于 IP=Y1、PORT=Y2。 IE。我希望能够在程序中的两个服务器之间进行写入和读取。 例如

write(Server1,buffer1);
read(Server1,buffer1);
write(Server2,buffer2);
read(Server2,buffer2);

我知道如何创建单个套接字客户端来与一台服务器通信,但我不确定与两台服务器通信的代码应该是什么样子。有人能引导我走向正确的方向/给我举个例子吗?

最诚挚的问候西蒙

最佳答案

很抱歉我的英语不好,并且给出了 Windows 代码,由于种种原因,我现在无法在 Linux 中编写代码,但我希望下次能这样做。

虽然windows版本一开始可能有点吓人,但仔细阅读代码就会清楚。另外,您必须从 Windows 到 POSIX Linux 版本进行一些更改,这是非常直接的(例如,使用 POSIX 线程而不是 Windows 线程)。

我已经创建了套接字来接收连接并按照您的预期更改接收发送模式中的消息。每个服务器可以接收的连接数受 MAX_THREADS 限制(每个线程管理一个连接)。请注意,select() 返回具有挂起连接的服务器套接字以调用accept()。

#include <winSock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <WS2tcpip.h>
#include <stdint.h>
#include <processthreadsapi.h>
#include <heapapi.h>

#define MAX_THREADS 20
#define MAX_BUFF_SIZE 256

struct thread_list
{
    HANDLE thread;
    struct thread_list *next;
};

struct MyData {
    char name_server[8];
    int sock;
};

void log_error(char *msg)
{
    printf(msg);
    exit(EXIT_FAILURE);
}

void initSocket(int *server, struct sockaddr_in *addr, char *ip, uint16_t porta){

    if ((*server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
        log_error("Erro socket\n");
    }

    addr->sin_port = htons(porta);
    addr->sin_addr.s_addr = inet_addr(ip);
    addr->sin_family = AF_INET;

    if((bind(*server, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0))
        log_error("ERROR bind()");

    if(listen(*server, SOMAXCONN) == SOCKET_ERROR)
        log_error("error listen()");

    return;
}

DWORD WINAPI ThreadFunc(void *data)
{
    char messageFrom[MAX_BUFF_SIZE], messageTo[MAX_BUFF_SIZE];
    struct MyData *ptr = (struct MyData *)data;

    // pattern: recv - send
    while(1)
    {
        recv(ptr->sock, messageFrom, MAX_BUFF_SIZE, 0);

        printf(messageFrom);

        strcpy(messageTo, "Message received. Complete send() message in your way");

        send(ptr->sock, messageTo, strlen(messageTo), 0);
    }

    // Save the whales, feed the hungry, free the mallocs()'s
}


int main( int argc, char **argv) {
    struct sockaddr_in addr1, addr2; 

    int server1, server2;

    struct MyData *pDataArray[MAX_THREADS];
    DWORD   dwThreadIdArray[MAX_THREADS];
    HANDLE  hThreadArray[MAX_THREADS]; 

    // init num current active threads
    int num_threads = 0;

    if(argc < 5)
        log_error("Format: ./prog ip1 port1 ip2 port2\n");

    initSocket(&server1, &addr1, argv[1], (uint16_t)atoi(argv[2]));
    initSocket(&server2, &addr2, argv[3], (uint16_t)atoi(argv[4]));

    int evtsock, novosock;

    fd_set readfds;

    FD_SET(server1, &readfds);
    FD_SET(server2, &readfds);

    struct sockaddr their_addr;
    socklen_t strg_sz = sizeof(their_addr);

    while(1) { //escuta conexoes

        evtsock = select(0, &readfds, NULL, NULL, NULL);
        pDataArray[num_threads]->sock = accept(evtsock, &their_addr, &strg_sz);

        if(pDataArray[num_threads]->sock == INVALID_SOCKET)
            log_error("ERROR accept()");

        if(num_threads == MAX_THREADS){
            // now this program will run forever. It is recommended to manage signals like SIGTERM
            // free mallocated memory and release all resources carefully
            printf("Max connections reached\n");
            continue;
        }

        pDataArray[num_threads] = (struct MyData *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
            sizeof(struct MyData));

        if(evtsock == server1)
            strcpy(pDataArray[num_threads]->name_server, "server1");
        else if(evtsock == server1)
            strcpy(pDataArray[num_threads]->name_server, "server2");
        else
            printf("Unmanaged event\n");

        hThreadArray[num_threads] = CreateThread(NULL, 0, ThreadFunc, &pDataArray[num_threads], 0, NULL);

        num_threads++;
    }

    return 0;
}

关于c - C 中两个服务器的套接字客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41896816/

相关文章:

c - 二维数组的堆缓冲区溢出

c# - 如何在 C# 中中止套接字

eclipse - Jetty HTTP/2 客户端示例

java - 为什么 `setConnectionRequestTimeout` 没有停止我的 1 分钟获取请求?

c++ - 如果由另一个 OpenMP 程序调用,则外部调用的 OpenMP 程序仅使用一个线程运行

在 C 中使用 memcmp 比较结构的一部分

套接字和多个 IP 地址

http - 发送连接升级后,如何将客户端http连接升级到golang中的websockets

c++ - 使 C/C++ Eclipse 工作

c++ - 通过 Win32 应用程序从 C/C++ 中的 UDP 端口读取