尽管我还很陌生,但我正在和C一起玩。在IRC中找出线程和锁的工作方式,连接的工作方式。
但是我遇到了错误,并且我不确定如何解决它。

波纹管是我得到的错误。

sample.c: In function ‘clientThreadEntry’:
sample.c:343:5: warning: passing argument 1 of ‘connectionMain’ makes pointer from integer without a cast [enabled by default]
     connectionMain(t->sock);
     ^
sample.c:216:5: note: expected ‘struct client_thread *’ but argument is of type ‘int’
 int connectionMain(struct client_thread *t) {




#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <string.h>
#include <strings.h>
#include <signal.h>
#include <netdb.h>
#include <time.h>
#include <errno.h>
#include <pthread.h>
#include <ctype.h>


struct client_thread {
    pthread_t thread;
    int thread_id;
    int sock;

    char nickname[32];

    int state;
#define DEAD 1
#define ALIVE 2
    int user_command_seen;
    int user_has_registered;
    time_t timeout;

    char line[1024];
    int line_len;

    int next_message;
};

/**
Allocate static structure for all client connections.
 */
#define MAX_CLIENTS 50
struct client_thread threads[MAX_CLIENTS];
/**
Number of connections we have open right now.
 */
int clientCount = 0;

pthread_rwlock_t message_log_lock = PTHREAD_RWLOCK_INITIALIZER;

#define MAX_MESSAGES 10000
char messageLogRecipients[MAX_MESSAGES];
char *messageLog[MAX_MESSAGES];
    int messageCount = 0;


int messageAppend(char *recipient, char *message) {

    /*
     If used up all message space, exit.
     */
    if (messageCount >= MAX_MESSAGES) return -1;
    // Append message.
    pthread_rwlock_wrlock(&message_log_lock);

    messageLogRecipients[messageCount] = strdup(recipient);
    message[messageCount] = strdup(message);
    messageCount++;

    pthread_rwlock_unlock(&message_log_lock);
    return 0;
}

int messageRead(struct client_thread *t) {
    pthread_rwlock_rdlock(&message_log_lock);

    int i;
    for (i = t->next_message + 1; i < messageCount; i++) {
    }

    t -> next_message = messageCount;

    pthread_rwlock_unlock(&message_log_lock);
    return 0;
}



int create_listen_socket(int port) {
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) return -1;

    int on = 1;
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) == -1) {
        close(sock);
        return -1;
    }
    if (ioctl(sock, FIONBIO, (char *) &on) == -1) {
        close(sock);
        return -1;
    }

    /* Bind it to the next port we want to try. */
    struct sockaddr_in address;
    bzero((char *) &address, sizeof (address));
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(port);
    if (bind(sock, (struct sockaddr *) &address, sizeof (address)) == -1) {
        close(sock);
        return -1;
    }

    if (listen(sock, 20) != -1) return sock;

    close(sock);
    return -1;
}

int accept_incoming(int sock) {
    struct sockaddr addr;
    unsigned int addr_len = sizeof addr;
    int asock;
    if ((asock = accept(sock, &addr, &addr_len)) != -1) {
        return asock;
    }

    return -1;
}

int read_from_socket(int sock, unsigned char *buffer, int *count, int buffer_size,
        int timeout) {
    fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, NULL) | O_NONBLOCK);


    int t = time(0) + timeout;
    if (*count >= buffer_size) return 0;
    int r = read(sock, &buffer[*count], buffer_size - *count);
    while (r != 0) {
        if (r > 0) {
            (*count) += r;
            break;
        }
        r = read(sock, &buffer[*count], buffer_size - *count);
        if (r == -1 && errno != EAGAIN) {
            perror("read() returned error. Stopping reading from socket.");
            return -1;
        } else usleep(100000);
        // timeout after a few seconds of nothing
        if (time(0) >= t) break;
    }
    buffer[*count] = 0;
    return 0;
}

/**
Function to check is a user has registered yet or not.
*/
int registrationCheck(struct client_thread *t) {
    if (t->user_has_registered)
        return -1;
    if (t->user_command_seen && t->nickname[0]) {
        // User has met registration requirements.
        t->user_has_registered = 1;
        t->timeout = 60;
        char msg[8192];
        snprintf(msg, 1024, ":myircServer.com 001 %s : You have registered.\n", t->nickname);
        write(t->sock, msg, strlen(msg));

        snprintf(msg, 1024, ":myircServer.com 002 %s : You have registered.\n", t->nickname);
        write(t->sock, msg, strlen(msg));

        snprintf(msg, 1024, ":myircServer.com 003 %s : You have registered.\n", t->nickname);
        write(t->sock, msg, strlen(msg));

        snprintf(msg, 1024, ":myircServer.com 004 %s : You have registered.\n", t->nickname);
        write(t->sock, msg, strlen(msg));

        snprintf(msg, 1024, ":myircServer.com 253 %s : Unknown connections\n", t->nickname);
        write(t->sock, msg, strlen(msg));

        snprintf(msg, 1024, ":myircServer.com 254 %s : Channels formed\n", t->nickname);
        write(t->sock, msg, strlen(msg));

        snprintf(msg, 1024, ":myircServer.com 255 %s : I have ??? clients and ??? servers.\n", t->nickname);
        write(t->sock, msg, strlen(msg));

        return 0;
    }
    return -1;
}


int connectionMain(struct client_thread *t) {

    int sock = t->sock;
    char nickname[8192];
    char msg[1024];
    snprintf(msg, 1024, ":myircserver.com 020 * :Greetings, from the IRC server\n");
    write(sock, msg, strlen(msg));
    unsigned char buffer[8192];
    int length = 0;

    t->timeout = 5;

    int timeOfLastData = time(0);

    while (1) {
        length = 0;
        messageRead(t);
        read_from_socket(sock, buffer, &length, 8192, 1);
        if (length > 0)
        {
           timeOfLastData = time(0);
        }
        if (length == 0 && ((time(0) - timeOfLastData) >= t->timeout)) {
            snprintf(msg, 1024, "ERROR :Closing Link: Connection timed out.. See ya!\n");
            write(sock, msg, strlen(msg));
            close(sock);
            return 0;
        }

        buffer[length] = 0;

        char channel[8192];
        int r = sscanf((char *) buffer, "JOIN %s", channel);
        if (r == 1) {
            if (!t->user_has_registered) {
                snprintf(msg, 1024, ":myircserver.com 241 * :JOIN command sent before registration\n");
                write(sock, msg, strlen(msg));
            }
        }


        r = sscanf((char *) buffer, "NICK %s", nickname);
        if (r == 1) {
            /**
            check and saw a nickname from the client.
            Need to handle what to do next.

        Checks if the nickname provided is less than 1 or greater than 30.
            if it is, then send and error since it is invalid and we cannot deal with nicknames of these sizes.
            if this isn't in place we would be trying to pass a string to big or too small to our nickname variable.
            */
            if (strlen(nickname) > 30 || strlen(nickname) < 1) {
                snprintf(msg, 1024, "ERROR :Inviliad nickname: Nickname too short or too long.\n");
                write(sock, msg, strlen(msg));
            } else {
                /**
                Nickname is a valid length!
                copy nickname to thread variable nickname.
                */
                strcpy(t->nickname, nickname);
                registrationCheck(t);
            }
        }
        /**
        Saw USER command if a NICK has been provided. Then mark connection.
        As registered. and send client greeting messages.
         If this isnt here, then we will not beable to handle USER command or the like.
         */
       if (!strncasecmp("USER ", (char *) buffer, 5)) {
           if (t->nickname) {
                /**
                Nickname has been provided and user has been registered.
                */
                t->user_command_seen = 1;
                registrationCheck(t);

            }
        }
        /**
        Checks if the messaged parsed is correct.
        Checks nickname, length and the response are correct and send the correct respose code.
        Checks of the PRIVMSG has at least 10 bytes of data to be used.

        Needed to see if there is data, and if it is sent before registration.
         */
        if (!strncasecmp("PRIVMSG", (char *) buffer, 7)) {
            if (!t->user_has_registered){
                snprintf(msg, 1024, ":myircserver.com 241 * :PRIVMSG command sent before registration\n");
                write(sock, msg, strlen(msg));
            } else {
            // Client is registered, so handle the message.
                char recipient[1024];
                char message [1024];
                if (sscanf((char *) buffer, "PRIVMSG %s :%[^\n]", recipient, message) == 2){
                    messageAppend(recipient, message);
                } else {
                // msg is wrongly formed, error.
                   snprintf(msg, 1024, ":myircserver.com 461 %s :Wrongly formed PRIVMSG command sent.\n", t->nickname);
                   write(sock, msg, strlen(msg));
                }
            }
        }
       /**
             * Client left, we must check and close this or we will get a SIGPIPE error that will kill program.
             * Send an error statement back to user so they know what is going on.
             */
        if (!strncasecmp("QUIT", (char *) buffer, 4)) {

            snprintf(msg, 1024, "ERROR :Closing Link: Connection timed out (see ya!)\n");
            write(sock, msg, strlen(msg));
            close(sock);
            return 0;
        }}


    close(sock);
    return 0;

}

void *clientThreadEntry(void *arg) {
    struct client_thread *t = arg;

    /**
    Run the threads connection handling code through threads.
     */

    connectionMain(t->sock);
    t->state = DEAD;
    return NULL;

}



int handleConnection(int sock) {


    printf("WE GET HERE\n");
    int i;
    for (i = 0; i < clientCount; i++) {
            if (threads[i].state == DEAD) {
                break;
            }}



        if (i > MAX_CLIENTS) {
            close(sock);
            return 1;
        }
    // clear out client structure, set up for threads.
        bzero(&threads[i], sizeof (struct client_thread));

    // store file descriptor into thread array.
        threads[i].sock = sock;
    threads[i].state = ALIVE;
        threads[i].thread_id = i;
        if (pthread_create(&threads[i].thread, NULL, clientThreadEntry, &threads[i]))
        {
            close(sock);
            return 1;
        }


        if (i == clientCount) clientCount++;


        return 0;
    }

    int main(int argc, char **argv) {
        signal(SIGPIPE, SIG_IGN);

        if (argc != 2) {
            fprintf(stderr, "usage: sample <tcp port>\n");
            exit(-1);
        }

        int master_socket = create_listen_socket(atoi(argv[1]));

        fcntl(master_socket, F_SETFL, fcntl(master_socket, F_GETFL, NULL)&(~O_NONBLOCK));

        while (1) {
            int client_sock = accept_incoming(master_socket);
            if (client_sock != -1) {
                // Got connection -- do something with it.

                handleConnection(client_sock);
            } else {usleep(10000);}
    }
}

最佳答案

您有一个编译警告。您的函数connectionMain使用client_thread指针:

int connectionMain(struct client_thread *t)
{


但是您使用sock整数来调用它:

void *clientThreadEntry(void *arg) {
    struct client_thread *t = arg;

    /**
    Run the threads connection handling code through threads.
     */

    connectionMain(t->sock);
    t->state = DEAD;
    return NULL;
}


大概您想这样称呼它:

    connectionMain(t);


至少可以解决编译警告。

关于c - C程序“struct client_thread *”出错,但参数的类型为“int”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26747814/

10-11 15:45