Проблемы при записи моего сокета Server.c, поддерживающего многопоточность - PullRequest
1 голос
/ 10 октября 2019

Как видно из названия, я создаю соединение сервер / клиент. Сервер позволит нескольким клиентам, в то время как клиенты могут общаться с сервером. У меня есть и серверные и клиентские файлы. Я не уверен, где я иду не так.

Я выполняю каждую строку в Cygwin

gcc server.c -o server lpthread
crashes :(

gcc client.c -o client
./client localhost 8080

Server.c

#include <stdio.h>
#include <stdlib.h>         // for IOs
#include <string.h> 
#include <unistd.h>
#include <sys/types.h>          // for system calls
#include <sys/socket.h>         // for sockets
#include <netinet/in.h>         // for internet 
#include <stdbool.h>
#include <pthread.h>            // for thread;

/* a function to print out error message and then abort */
void error(const char *msg) {
    perror(msg);
    exit(1);
}

void *threadFunct(int mySockfd) {
    char buffer2[256];  
    bool exitFlag = false;
    int read_writeLen;
    while(!exitFlag) {
        bzero(buffer2, 256);
        read_writeLen = read(mySockfd, buffer2, 255);
        if (read_writeLen < 0)
            printf("ERROR reading from the client socket\n");

        if(strcmp(buffer2,"EXIT\n")==0) {
            printf("Now socket %d will be close\n", mySockfd);
            close(mySockfd);
            pthread_exit(mySockfd);     // terminate the calling thread

        } else {
            printf("The message read from socket %d :%s\n ",mySockfd,buffer2);
            read_writeLen = write(mySockfd,"I got Your Message" , 18);
            if (read_writeLen < 0)
                printf("Unable to write to socket\n");
        }
    }
    close(mySockfd);
    return  NULL;

}
int main(int argc, char *argv[]) {
    int sockfd, newsockfd, portno;
    socklen_t clilen;
    char buffer[256];
    struct sockaddr_in serv_addr, cli_addr;
    int charRead_Written;
    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");


    while(true) {
        pthread_t  threadId;

        listen(sockfd,10);
        clilen = sizeof(cli_addr);
        newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
        if(newsockfd<0)
            error("ERROR on accept");
        pthread_create(&threadId,NULL,threadFunct,newsockfd);
    }

    close(sockfd);
    return 0;
}

Client.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdbool.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;
    bool running = false; // Keep running until the user types EXIT

    // gcc client.c -o client
    // ./client localhost port
    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");
    while(!running) {
        printf("Please Enter The message: ");
        bzero(buffer, 256);
        fgets(buffer, 255, stdin);
        n = write(sockfd, buffer, strlen(buffer));
        if(n<0)
            error("ERROR writing from socket");

        if(strcmp(buffer, "EXIT\n")== 0)
        {
            running = true;
            break;
        }
        bzero(buffer,256);
        n = read(sockfd, buffer,255);
        if(n < 0)
            printf("ERROR reading from  socket");
        printf("%s\n", buffer);

    }
    close(sockfd);

    return 0;
}

Файл client.c компилируется и работает нормально. Файл server.c не компилируется и не уверен, как решить проблемы. Ниже приведены результаты компиляции для server.c.

server.c: In function ‘threadFunct’:
server.c:39:17: warning: passing argument 1 of ‘pthread_exit’ makes pointer from integer without a cast [-Wint-conversion]
    pthread_exit(mySockfd);  // terminate the calling thread
                 ^~~~~~~~
In file included from server.c:18:0:
/usr/include/pthread.h:150:6: note: expected ‘void *’ but argument is of type ‘int’
 void pthread_exit (void *) __attribute__ ((__noreturn__));
      ^~~~~~~~~~~~
server.c: In function ‘main’:
server.c:85:36: warning: passing argument 3 of ‘pthread_create’ from incompatible pointer type [-Wincompatible-pointer-types]
      pthread_create(&threadId,NULL,threadFunct,newsockfd);
                                    ^~~~~~~~~~~
In file included from server.c:18:0:
/usr/include/pthread.h:146:5: note: expected ‘void * (*)(void *)’ but argument is of type ‘void * (*)(int)’
 int pthread_create (pthread_t *, const pthread_attr_t *,
     ^~~~~~~~~~~~~~
server.c:85:48: warning: passing argument 4 of ‘pthread_create’ makes pointer from integer without a cast [-Wint-conversion]
      pthread_create(&threadId,NULL,threadFunct,newsockfd);
                                                ^~~~~~~~~
In file included from server.c:18:0:
/usr/include/pthread.h:146:5: note: expected ‘void *’ but argument is of type ‘int’
 int pthread_create (pthread_t *, const pthread_attr_t *,

1 Ответ

1 голос
/ 10 октября 2019

Вместо этого:

pthread_exit(mySockfd);     // terminate the calling thread

Это:

pthread_exit(NULL);     // terminate the calling thread

Вместо этого:

void *threadFunct(int mySockfd)

Это:

struct MyArgs
{
    int mySockfd;
};

void *threadFunct(void* args)
{
    int mySockfd = ((struct MyArgs*)args)->mySockfd;

Затем создайте поток следующим образом:

 struct MyArgs* args = (struct MyArgs*)malloc(sizeof(struct MyArgs));
 args->mySockfd = mySockfd;
 pthread_create(&threadId,NULL,threadFunct,(void*)args);

Вы сами по себе должным образом вызовете free для этой структуры выделения после , когда поток вышел или собирается завершить работу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...