0

我在 C 中有一个简单的客户端和服务器程序,通过 TCP 进行通信。客户端向服务器发送消息,服务器将其写入文件。

我需要客户端无限循环,直到它读取 EOF 字符,并让服务器继续为请求提供服务。但是,目前我遇到了循环问题。它工作正常,没有任何循环,但是当我在客户端中放置一个 while(1) 时,服务器服务第一个请求很好,但第二个没有做任何事情,第三个导致管道损坏错误。我认为这是因为服务器过早地关闭了套接字,但我一直坚持如何修复它。

这是我的客户程序:

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


#define BUFFERLENGTH 256

/* displays error messages from system calls */
void error(char *msg)
{
    perror(msg);
    exit(0);
}

int main(int argc, char *argv[])
{
    int sockfd, portno, n;
    struct sockaddr_in serv_addr;
    struct hostent *server;

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

    /* create socket */
    portno = atoi (argv[2]);
    sockfd = socket (AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) 
        error ("ERROR opening socket");

    /* enter connection data */
    server = gethostbyname (argv[1]);
    if (server == NULL) {
        fprintf (stderr, "ERROR, no such host\n"); // error message for when the provided hostname doesn't exist. 
        exit (1);
    }
    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);

    /* connect to the server */
    if (connect (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) 
        error ("ERROR connecting");
while(1){
    /* prepare message */
    printf ("Please enter the message: ");
    bzero (buffer, BUFFERLENGTH);
    fgets (buffer, BUFFERLENGTH, stdin);

    /* send message */
    n = write (sockfd, buffer, strlen(buffer));
    if (n < 0) 
         error ("ERROR writing to socket");
    bzero (buffer, BUFFERLENGTH);

    /* wait for reply */
    n = read (sockfd, buffer, BUFFERLENGTH -1);
    if (n < 0) 
         error ("ERROR reading from socket");
    printf ("%s\n",buffer);

}
return 0;
}

和服务器代码:

/* A threaded server which uses TCP to communicate with clients.
       Passes the port number and a file name in as arguments.
       Receives log entries from the clients and writes them to the file. */
    #include <stdio.h>
    #include <sys/types.h> 
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <ctype.h>
    #include <stdlib.h>
    #include <strings.h>
    #include <string.h>
    #include <unistd.h>
    #include <pthread.h>

    #define BUFFERLENGTH 256

    /* displays error messages from system calls */
    void error(char *msg)
    {
        perror(msg);
        exit(1);
    }

    FILE *file;
    int returnValue; 
    pthread_mutex_t mut; /* the lock */

    /* the procedure called for each request */
    void *processRequest (void *args) {
      int *newsockfd = (int *) args;
      char buffer[BUFFERLENGTH];
      int n, formed = 0;

      n = read (*newsockfd, buffer, BUFFERLENGTH -1);
      if (n < 0) 
        error ("ERROR reading from socket");

      printf ("Here is the message: %s\n",buffer);
      pthread_mutex_lock (&mut); /* lock exclusive access to variable isExecuted */

        //const char* string = "hello world";
        char buffer2[256];
        char* walker;
        int colon = 0;


        strcpy(buffer2,buffer);

    walker=buffer2;

    while(colon == 0){

        if(*walker == ':'){ // if it encounters a colon will successfully exit the loop.
            colon = 1;
        }
        if(*walker == '\0'){ // if it encounters the end of the string, will break the loop.
            break;
        }
        if(isalnum(*walker)){ // if it's not an alphanumeric character then it will break the loop, otherwise it will continue.
            walker++;
    } else {
    break;}

    }

    if(colon == 1){ // if the loop found a colon, then it will continue to search the rest of the string.
        while(*walker >= 32 && *walker<= 126){
                ++walker;
            if(*walker == '\n'){
                printf("Entry well formed.\n");
                fprintf(file,"%s",buffer); /*writes*/
                    fclose(file); /*done!*/ 
                formed = 1;
            }
            } 
    } else{
        perror("Entry not well formed.\n");
    }

      pthread_mutex_unlock (&mut); /* release the lock */

    if(formed==1){
      n = sprintf (buffer, "Message received and written to file.\n");
    }else{
        n = sprintf (buffer, "Message received but was not well formed and was not written to file.\n");
    }
      /* send the reply back */
      n = write (*newsockfd, buffer, BUFFERLENGTH);
      if (n < 0) 
        error ("ERROR writing to socket");

      close (*newsockfd); /* important to avoid memory leak */  
      free (newsockfd);

      returnValue = 0;  /* cannot guarantee that it stays constant */
      pthread_exit (&returnValue);
    }



    int main(int argc, char *argv[])
    {
         socklen_t clilen;
         int sockfd, portno;
         char buffer[BUFFERLENGTH];
         struct sockaddr_in serv_addr, cli_addr;
         pthread_t *server_thread;
         int result;


         if (argc < 3) {
             fprintf (stderr,"ERROR, arguments: port filename.\n"); /* Error message for if there isn't enough arguments. */
             exit(1);
         }


         /* create socket */
         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);

         /* bind it */
         if (bind(sockfd, (struct sockaddr *) &serv_addr,
                  sizeof(serv_addr)) < 0) 
                  error("ERROR on binding");

         /* ready to accept connections */
         listen (sockfd,5);
         clilen = sizeof (cli_addr);

         /* now wait in an endless loop for connections and process them */
         while (1) {

          file = fopen(argv[2], "a");
          if (file == NULL) {
             printf("I couldn't open results.txt for writing.\n");
             exit(0);
          }
           int *newsockfd; /* allocate memory for each instance to avoid race condition */
           pthread_attr_t pthread_attr; /* attributes for newly created thread */

           newsockfd  = malloc (sizeof (int));
           if (!newsockfd) {
         fprintf (stderr, "Memory allocation failed!\n");
         exit (1);
           }
           /* waiting for connections */
           *newsockfd = accept(sockfd, 
                  (struct sockaddr *) &cli_addr, 
                  &clilen);
           if (*newsockfd < 0) 
         error ("ERROR on accept");
           bzero (buffer, BUFFERLENGTH);

         /* create separate thread for processing */
         server_thread = malloc (sizeof (pthread_t));
         if (!server_thread) {
         fprintf (stderr, "Couldn't allocate memory for thread!\n");
         exit (1);
           }

         if (pthread_attr_init (&pthread_attr)) {
         fprintf (stderr, "Creating initial thread attributes failed!\n");
         exit (1);
         }

         if (pthread_attr_setdetachstate (&pthread_attr, !PTHREAD_CREATE_DETACHED)) {
             fprintf (stderr, "setting thread attributes failed!\n");
         exit (1);
         }
         result = pthread_create (server_thread, &pthread_attr, processRequest, (void *) newsockfd);
           if (result != 0) {
         fprintf (stderr, "Thread creation failed!\n");
         exit (1);
           }


         }
         return 0; 
    }
4

1 回答 1

2

请注意,您的服务器代码已被严重粘贴,并且包含多个main()混合副本。

在服务器中,您调用accept()以接收客户端连接。然后创建一个线程来处理连接。该线程只处理一条消息并退出,但它应该为来自客户端的所有消息提供服务,直到客户端受够了。

因此,您需要在服务器线程中放置一个循环以允许它处理多条消息。

请注意,当我运行您的服务器时,线程处理的第一条消息被正确接收(消息读取“hello”),但报告格式错误(消息Entry not well formed.)。在 OS-X 上运行。

另请注意,该行:

if (pthread_attr_setdetachstate (&pthread_attr, !PTHREAD_CREATE_DETACHED)) {

不应该有'!' 在常量 PTHREAD_CREATE_DETACHED 前面。

于 2012-10-28T23:15:45.023 回答