C程序“struct client_thread*”中出错,但参数的类型为“int”



虽然我对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 connectionsn", t->nickname);
        write(t->sock, msg, strlen(msg));
        snprintf(msg, 1024, ":myircServer.com 254 %s : Channels formedn", 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 servern");
    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 registrationn");
                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 registrationn");
                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 HEREn");
    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);

这至少可以修复编译警告。

相关内容

最新更新