通过 C 中的套接字连接到服务器的多个连接

Multiple connections to server via socket in C

基本上我的程序应该能够同时与服务器建立多个连接。我有 运行,除非他们必须通过套接字发送大量文本,否则这是不可预测的。有时有效,有时无效。 plaintext4 文件长 69,333 字节,当我尝试通过套接字通过网络同时将它发送 5 次到服务器并返回时,它并不总是有效;有时它有效,有时它的一部分丢失,等等。当我使用基本上相同的东西使用写和读时它有效,但是当我尝试对大量文本进行相同时,它几乎根本不起作用,因此为什么我切换到发送和接收。现在我不知道如何做到这一点,所以当有人在某个时间发送时,没有其他人会同时发送……因为我认为这就是我遇到的问题。任何帮助都会很棒。

我的程序现在的状态:

- 发送少量文本时有效。

- 发送大量文本时不起作用。

- 它在不工作时创建的文件大小可能会有所不同,有时超过 60K 字节,有时甚至只有 20K 字节。这意味着在正确的进程接收到它之前,其他进程之一可能写入套接字或从中读取。 (我觉得)。

服务器代码

#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[])
{
    const int BUFF_SIZE = 70000;
    int sockfd, newsockfd, portno, newsockfdc;
    socklen_t clilen;
    char buffer[BUFF_SIZE];
    pid_t pid;
    int status;
    char temp[BUFF_SIZE];
    struct sockaddr_in serv_addr, cli_addr;
    int n;
    int i;
    if (argc < 2) {
     fprintf(stderr,"ERROR, no port provided\n");
     exit(1);
    }
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) 
    error("ERROR opening socket");
    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = atoi(argv[1]);
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);
    if (bind(sockfd, (struct sockaddr *) &serv_addr,
          sizeof(serv_addr)) < 0) 
          error("ERROR on binding");
    listen(sockfd,5);
    while(1){
        waitpid(-1, &status, WNOHANG);
        memset(buffer, '[=10=]', sizeof(buffer));
        clilen = sizeof(cli_addr);
        newsockfd = accept(sockfd, 
             (struct sockaddr *) &cli_addr, 
             &clilen);
        if (newsockfd < 0) 
          error("ERROR on accept");
        if((pid=fork())==0)     
        {
            close(sockfd);          
            int d;
            for(i=0; i<1; i++)
            {
                bzero(buffer,BUFF_SIZE);
                //sleep(1);
                d=BUFF_SIZE-1;      
                //n = read(newsockfd,buffer,d);             
                n = recv(newsockfd, buffer, sizeof(buffer), 0);
                if (n < 0) error("ERROR reading from socket");
                bzero(temp, BUFF_SIZE);
                strcpy(temp, buffer);

                n = send(newsockfd, buffer, strlen(buffer)+1, 0);
                //n = write(newsockfd,temp,sizeof(temp));
                if (n < 0) error("ERROR writing to socket");
            }
            close(newsockfd);
            exit(0);
        }
        else{ 
            waitpid(-1, &status, WNOHANG);
            close(newsockfd);
        }
    }
    close(sockfd);
    return 0; 
}

客户代码

#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[])
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    const int BUFF_SIZE = 70000;
    char buffer[BUFF_SIZE];
    if (argc < 4) {
        fprintf(stderr,"usage %s hostname port\n", argv[0]);
        exit(0);
    }
    int numt;
    numt = atoi(argv[3]);
    char numc[5];
    bzero(numc, 5);
    sprintf(numc, "%d", numt);
    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");
    bzero(buffer,BUFF_SIZE);
    FILE *fp;
    size_t bytes_read;  
    if((fp=fopen("./plaintext4", "r+"))==NULL)
    {
        perror("fopen(2) file error");
        exit(EXIT_FAILURE);
    } 
    bytes_read = fread(buffer, sizeof(buffer), 1, fp);
    fclose(fp);
    sleep(1);   
    n=send(sockfd, buffer, strlen(buffer)+1, 0);
    if (n < 0) 
        error("ERROR writing to socket");
    bzero(buffer,BUFF_SIZE);
    n=BUFF_SIZE - 1;

    n = recv(sockfd, buffer, sizeof(buffer), 0);
    if (n < 0) 
        error("ERROR reading from socket");

    char filei[90];
    bzero(filei,90);
    strcpy(filei, "plaintext");
    strcat(filei, numc);
    strcat(filei, "_a");
    if((fp=fopen(filei, "w+"))==NULL)
    {
        perror("fopen(2) file error");
        exit(EXIT_FAILURE);
    } 
    bytes_read = fwrite(buffer, strlen(buffer), 1, fp);
    fclose(fp);
    close(sockfd);
    return 0;
    //sleep(1);
    printf("Sending message 1: plaintext1\n");
    bzero(buffer,BUFF_SIZE);
    if((fp=fopen("./plaintext1", "r+"))==NULL)
    {
        perror("fopen(2) file error");
        exit(EXIT_FAILURE);
    } 
    bytes_read = fread(buffer, sizeof(buffer), 1, fp);
    fclose(fp);
    n = send(sockfd, buffer, strlen(buffer)+1, 0);  
    //n = write(sockfd, buffer, strlen(buffer));
    if (n < 0)
        error ("ERROR writing to socket client side");
    bzero(buffer, BUFF_SIZE);
    n=BUFF_SIZE - 1;
    n = recv(sockfd, buffer, sizeof(buffer), 0);
    //n = read(sockfd, buffer, n);
    if (n < 0) 
        error("ERROR reading from socket client side");
    printf("message: %s\n", buffer);
    strcat(filei, "b");
    if((fp=fopen(filei, "w+"))==NULL)
    {
        perror("fopen(2) file error");
        exit(EXIT_FAILURE);
    } 
    bytes_read = fwrite(buffer, strlen(buffer), 1, fp);
    fclose(fp);
    close(sockfd);
    return 0;
}

您的服务器进程(调用 accept() 的进程)可能会被 waitpid 阻塞 - 这可能是您遇到问题的原因。 或者,您可以通过 SIGCHLD 信号处理程序实现 waitpid 调用,并从 main().

中删除 waitpid

此致!