c - C 程序错误 ‘struct client_thread *’ 但参数类型为 ‘int’

标签 c multithreading function

虽然我对 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/

相关文章:

使用 Concurrent.Futures 模块作为 ThreadPool 调用 Python-get 函数的返回值

java - 如何在没有 Selenium 网格的情况下在浏览器的多个实例中并行运行单个测试用例

javascript - 如何在 Javascript 中用单个变量编写多个参数?

c++ - 混淆内联函数的问题

c - 编译 OCILIB OCI Wrapper 库的问题

c - C 中的垂直翻转位图不起作用

c - 指向字符数组的指针如何表现?

c++ - 选择功能 windows vs linux

linux - 使 bash 脚本多线程

javascript - jQuery 中使用 bind() 和each() 分配事件处理程序的区别?