套接字编程:如何在c中处理多个客户端

时间:2016-12-07 02:36:52

标签: c sockets

我正在尝试编写的程序需要帮助。该程序应该有3个客户端通过套接字连接到它。

我正在寻找一些方向。

如何等待服务器程序连接到所有3个客户端。

如何区分连接。即写入客户端1但不写入2或写入所有客户端连接。

如何使用fork()。

我能够编写服务器和客户端程序,但我无法想到多个客户端的解决方案。

如果有人可以帮我解决这个问题,那将会很棒。非常感谢你。

编辑:到目前为止,我有服务器程序等到3个客户端已连接。所有3个客户端完成但服务器程序显示“从套接字读取错误:错误的文件描述符”

我的客户端代码如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 

void error(const char *msg)
{
    perror(msg);
    exit(0);
}

int main(int argc, char *argv[])
{

    char router_no[256] = "0";
    int cost_to_router_0 = 0;
    int cost_to_router_1 = 1;
    int cost_to_router_2 = 3;
    int cost_to_router_3 = 7;

    printf("\n\n");
    printf("Initial table for Router 0(Client)\n");
    printf("===================================================\n");
    printf("Destination Router    |Link Cost                  |\n");
    printf("===================================================\n");
    printf("Router 0              |%d                          |\n", cost_to_router_0);
    printf("Router 1              |%d                          |\n", cost_to_router_1);
    printf("Router 2              |%d                          |\n", cost_to_router_2);
    printf("Router 3              |%d                          |\n", cost_to_router_3);
    printf("===================================================\n");

    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;


    char buffer[256];
    if (argc < 3) {
       fprintf(stderr,"usage %s hostname port\n", argv[0]);
       exit(0);
    }

    portno = atoi(argv[2]);

    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if (sockfd < 0) 
        error("ERROR opening socket");

    server = gethostbyname(argv[1]);

    if (server == NULL) {
        fprintf(stderr,"ERROR, no such host\n");
        exit(0);
    }

    bzero((char *) &serv_addr, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;

    bcopy((char *)server->h_addr, 
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);

    serv_addr.sin_port = htons(portno);

    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
        error("ERROR connecting");

    printf("\n");    
    printf("Clients Router Number: %s \n", router_no);
    printf("Cost to Router 0(Client): %d \n", cost_to_router_0);
    printf("Cost to Router 1(Server): %d \n", cost_to_router_1);
    printf("Cost to Router 2:         %d \n", cost_to_router_2);
    printf("Cost to Router 3:         %d \n", cost_to_router_3);
    printf("\n");

    //printf("Please enter the message: ");
    //bzero(buffer,256);
    //fgets(buffer,255,stdin);

    // Send Router Number
    n = write(sockfd,router_no,strlen(router_no));    
    if (n < 0) 
         error("ERROR writing to socket");

    // Send Cost of Router 0 to other Routers     
    n = write(sockfd, &cost_to_router_1, sizeof(cost_to_router_1));
    n = write(sockfd, &cost_to_router_2, sizeof(cost_to_router_2));
    n = write(sockfd, &cost_to_router_3, sizeof(cost_to_router_3));

    if (n < 0) 
         error("ERROR writing to socket"); 

    int cost_server_to_router_0 = 0;
    int cost_server_to_router_1 = 0;
    int cost_server_to_router_2 = 0;
    int cost_server_to_router_3 = 0;

    bzero(buffer,256);
    n = read(sockfd, &cost_server_to_router_0, sizeof(cost_server_to_router_0));
    n = read(sockfd, &cost_server_to_router_0, sizeof(cost_server_to_router_1));
    n = read(sockfd, &cost_server_to_router_2, sizeof(cost_server_to_router_2));     
    n = read(sockfd, &cost_server_to_router_3, sizeof(cost_server_to_router_3));

    printf("Costs of Router 1(Server) to other Routers\n");
    printf("Cost to Router 0:         %d \n", cost_server_to_router_0);
    printf("Cost to Router 1:         %d \n", cost_server_to_router_1);
    printf("Cost to Router 2:         %d \n", cost_server_to_router_2);
    printf("Cost to Router 3:         %d \n", cost_server_to_router_3);

    bzero(buffer,256);
    n = read(sockfd,buffer,255);

    if ( cost_to_router_1 + cost_server_to_router_0 < cost_to_router_0)

        cost_to_router_0 = cost_to_router_1 + cost_server_to_router_0;

    if ( cost_to_router_1 + cost_server_to_router_1 < cost_to_router_1)

        cost_to_router_1 = cost_to_router_1 + cost_server_to_router_1;

    if ( cost_to_router_1 + cost_server_to_router_2 < cost_to_router_2)

        cost_to_router_2 = cost_to_router_1 + cost_server_to_router_2;        

    if ( cost_to_router_1 + cost_server_to_router_3 < cost_to_router_3)

        cost_to_router_3 = cost_to_router_1 + cost_server_to_router_3;


    printf("\n\n");
    printf("Updated table for Router 0(Client)\n");
    printf("===================================================\n");
    printf("Destination Router    |Link Cost                  |\n");
    printf("===================================================\n");
    printf("Router 0              |%d                          |\n", cost_to_router_0);
    printf("Router 1              |%d                          |\n", cost_to_router_1);
    printf("Router 2              |%d                          |\n", cost_to_router_2);
    printf("Router 3              |%d                          |\n", cost_to_router_3);
    printf("===================================================\n");


    if (n < 0) 
         error("ERROR reading from socket");
    printf("%s\n",buffer);
    close(sockfd);
    return 0;
}

请记住,这是我使用我发现的教程编写的单个处理客户端程序。我需要能够修改它以连接并保持与多个客户端的连接

我的服务器代码如下:

/* A simple server in the internet domain using TCP
   The port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

void error(const char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{

     int number_of_clients = 0;
     char router_no[256] = "1";
     int cost_to_router_0 = 1;
     int cost_to_router_1 = 0;
     int cost_to_router_2 = 1;
     int cost_to_router_3 = 10000; // This is set to 10,000 because there is not link
                                   // between router 1 to router 3 and/but infinity
                                   // is not a real number.

     int sockfd, newsockfd, portno;
     socklen_t clilen;
     char buffer[256];
     struct sockaddr_in serv_addr, cli_addr;
     int n;
     if (argc < 2) {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }

     // Socket is opened
     sockfd = socket(AF_INET, SOCK_STREAM, 0);

     // Displays error if socket opening was not suscessful
     if (sockfd < 0) 
        error("ERROR opening socket");

     // Sets serv_addr to zeros
     bzero((char *) &serv_addr, sizeof(serv_addr));

     // Sets port number to argument passed in call
     portno = atoi(argv[1]);

     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);

     // Biding socket to an adress
     if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0) 
              error("ERROR on binding");

     listen(sockfd,5);

     clilen = sizeof(cli_addr);

     while (1)// start of while
     {

     while (number_of_clients < 3)
     {
     newsockfd = accept(sockfd, 
                 (struct sockaddr *) &cli_addr, 
                 &clilen);

     if (newsockfd < 0) 
          error("ERROR on accept");
          else number_of_clients ++;

     }

     bzero(buffer,256);
     n = read(newsockfd,buffer,255);
     if (n < 0) error("ERROR reading from socket");
     printf("Client Router's Number: %s\n", buffer);

     int cost_client_to_router_1 = 0;
     int cost_client_to_router_2 = 0;
     int cost_client_to_router_3 = 0;

     bzero(buffer,256);
     n = read(newsockfd, &cost_client_to_router_1, sizeof(cost_client_to_router_1));
     n = read(newsockfd, &cost_client_to_router_2, sizeof(cost_client_to_router_2));
     n = read(newsockfd, &cost_client_to_router_3, sizeof(cost_client_to_router_3));

     if (n < 0) error("Error reading from socket");
     printf("Cost from client to router 1: %d \n", cost_client_to_router_1);
     printf("Cost from client to router 2: %d \n", cost_client_to_router_2);
     printf("Cost from client to router 3: %d \n", cost_client_to_router_3);


     n = write(newsockfd, &cost_to_router_0, sizeof(cost_to_router_0));
     n = write(newsockfd, &cost_to_router_0, sizeof(cost_to_router_0));
     n = write(newsockfd, &cost_to_router_2, sizeof(cost_to_router_2));
     n = write(newsockfd, &cost_to_router_3, sizeof(cost_to_router_3));

     if (n < 0) error("ERROR writing to socket");
     close(newsockfd);

     } //end of while
     close(sockfd);


     return 0; 
}

服务器代码无法正常工作,因为我缺少对fork()和select()

的理解

1 个答案:

答案 0 :(得分:1)

  

如何等待服务器程序连接到所有3个客户端。

通过三次致电accept

  

如何区分连接。即写入客户端1但不写入2或写入所有客户端连接。

它们都有accept返回的不同文件描述符。您当前的服务器代码会忘记前两个(通过覆盖newsockfd)并仅将最后一个存储在newsockfd中。不要这样做,原因很明显。

  

如何使用fork()。

这还不足以得到答案。

  

所有3个客户端完成但服务器程序显示“从套接字读取错误:错误的文件描述符”

那是因为服务器关闭了最后一个客户端的文件描述符(记住它忘了前两个),然后不等待另一个客户端(因为number_of_clients已经是3),然后尝试从文件中读取描述它刚关闭。