连接中的套接字编程错误

时间:2016-05-04 04:19:13

标签: linux multithreading sockets server client

我正在尝试进行Socket编程。我谷歌,看着像我这样的问题。但是,我无法弄清楚我的错误。

每当我运行代码时,mainclient.c的{​​{1}}都会收到错误。错误是invalid argument

Server.c

/* chatroom server */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <pthread.h>
#include <signal.h>


#define MAX_ROOMS 36
#define MAX_NAME_SIZE 56
#define PORT_NUM 12333
#define MSG_SIZE 8
#define MAX_LOAD 246
#define MAX_CRC 64 //max clients
#define MAX_BUF 256
#define SERVER_IP 32
#define DEBUG 0

struct msg {
    int type; //create, join, delete
    int length; // length or port num
};

struct chat_room {
    int socket_d; //socket descriptor
    int port;
    pthread_t id; //id of chatroom
    char name[MAX_NAME_SIZE];
    int clients[MAX_ROOMS];  // used to hold the client's master sockets
};

struct chat_room* findRoom(char* name, struct chat_room* chat){

    int iterator;

    for(iterator = 0; iterator < MAX_ROOMS; iterator++){
        if(strcmp(name, chat[iterator].name) && (chat[iterator].port != 0)) {
            return &chat[iterator];
        }
    }

    //if room does not exist
    return NULL;    
}

struct chat_room* joinServer(int chat_socket, char* name, struct chat_room* chat){

    struct chat_room* local_chat = findRoom(name, chat);
    int i;
    if(local_chat != NULL){ //if the chat exists
        for(i= 0; i< MAX_CRC; i++){
            if(local_chat->clients[i] == 0)
            {
                local_chat->clients[i] = chat_socket;
            }
            return local_chat;
        }
    }

    //if server if full or else error
    return NULL; 
}

int createResponse(int chat_socket, int new_port_num, int type){
    struct msg temp;
    char temp_buff[MAX_LOAD];

    memset(temp_buff, 0, MAX_LOAD);
    temp.type = type; 
    temp.length = new_port_num;

    memcpy(temp_buff, &temp, sizeof(temp));

    write(chat_socket, temp_buff, MSG_SIZE);

    return 0;
}

int joinResponse(int chat_socket, int new_port_num){
    struct msg temp;
    char temp_buff[MAX_LOAD];

    memset(temp_buff, 0, MAX_LOAD);
    temp.type = 11; 
    temp.length = new_port_num;

    memcpy(temp_buff, &temp, sizeof(temp));

    write(chat_socket, temp_buff, MSG_SIZE);

    return 0;
}

int deleteResponse(int chat_socket, struct chat_room* chat){
    struct msg temp;
    char temp_buff[MAX_LOAD];
    int i; 
    memset(temp_buff, 0, MAX_LOAD);
    temp.type = 12; 

    memcpy(temp_buff, &temp, sizeof(temp));

    for(i=0; i<MAX_CRC; i++){
        if((chat->clients[i] != chat_socket) && (chat->clients[i] != 0))
            write(chat->clients[i],temp_buff, MSG_SIZE);
    }

    return 0;
}

struct chat_room* addRoom(int chat_socket, char* name, struct chat_room* chat){

    int socket_d;
    int i;
    struct sockaddr_in sock;

    static int port = PORT_NUM;

    memset(&sock, 0, sizeof(sock));

    int temp = -1;

    for(i = 0; i<MAX_ROOMS; i++){
        if((strcmp(chat[i].name, name) == 0) && (chat[i].port != 0)){
            createResponse(chat_socket, chat[i].port, 15);
            return NULL;
        }
        else if((chat[i].port == 0) && (temp== -1)){
            temp = i;
        }
    }

    if(temp == -1){
        return NULL;
    }

    socket_d = socket(AF_INET, SOCK_STREAM, 0);

    if(socket_d == -1 && DEBUG){
        perror("Error creating chatroom socket");
        return NULL;
    }

    sock.sin_family = AF_INET;
    port++;
    sock.sin_port = htons(port);

    if(bind(socket_d, (struct sockaddr*)&sock, sizeof(struct sockaddr_in)) == -1){
        perror("error in binding ");
        return NULL;
    }

    chat[temp].socket_d = socket_d;
    chat[temp].port = port;
    strcpy(chat[temp].name, name);

    return &chat[temp];

}

void* chat_room_main(void* chat_room_cluster){

    char buf[MAX_LOAD];

    int socket_d, chat_socket;
    int temp; //temp_fd
    int read_val;
    int num_clients = 0;
    int i;
    int clients[MAX_CRC];

    fd_set allfd, modfd;

    struct chat_room chat_room_para;

    memcpy(&chat_room_para, (struct chat_room*)chat_room_cluster, sizeof(struct chat_room));
    free(chat_room_cluster);

    memset(clients, 0, sizeof(int)*MAX_CRC);
    socket_d = chat_room_para.socket_d;

    listen(socket_d, 1);

    FD_ZERO(&allfd);
    FD_SET(socket_d, &allfd);
    printf("New Chatroom Started\n");
    while(1){
        modfd = allfd;
        select(FD_SETSIZE, &modfd, NULL, NULL, NULL);

        for(temp = 0; temp < FD_SETSIZE; temp++){
            if(FD_ISSET(temp, &modfd)){

                memset(buf, 0, sizeof(buf));

                if(temp == socket_d) {

                    chat_socket = accept(socket_d, NULL, NULL);
                    FD_SET(chat_socket, &allfd);


                    // find an empty spot to add the chat room
                    for(i = 0; i<MAX_CRC; i++) {
                        if(clients[i] == 0){
                            clients[i] = chat_socket;
                            break;
                        }
                    }

                    sprintf(buf, "Number of people in chatroom: %d", num_clients);
                    write(chat_socket, buf, strlen(buf));
                    num_clients++;
                }
                else{
                    if(read_val = read(temp, buf, MAX_LOAD) > 0){
                        for(i = 0; i< MAX_CRC; i++){
                            if((clients[i] != temp) && (clients[i] != 0)){
                                write(clients[i], buf, read_val);
                            }
                        }
                    }
                    else if(read_val <= 0) {
                        FD_CLR(temp, &allfd);

                        for(i = 0; i<MAX_CRC; i++){
                            if(clients[i] == temp)
                                clients[i] = 0;
                        }
                        num_clients--;
                        close(chat_socket);
                    }
                }
            }
        }
    }   

}

int main(int argc, char* argv[]){

    int server_socket, chat_socket; //file descriptors for server and chat
    int temp; //tempfd 
    int i, j;

    char server_ip[SERVER_IP];
    char buf[MAX_BUF];
    char msg_buf[MSG_SIZE];

    fd_set allfd, modfd;

    struct sockaddr_in sock;
    struct hostent* host_name;

    struct chat_room chatrooms[MAX_ROOMS];

    memset(chatrooms, '\0', sizeof(struct chat_room)* MAX_ROOMS);
    memset(&sock, '\0', sizeof(sock));

    server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if(server_socket == -1){
        perror("Error creating socket");
        return -1;
    }

    sock.sin_family = AF_INET;
    sock.sin_port = htons(PORT_NUM);
    sock.sin_addr.s_addr = INADDR_ANY;

    if((bind(server_socket, (struct sockaddr*)&sock, sizeof(struct sockaddr_in))) == -1){
        perror("Error in bind()");
        return -1;
    }

    listen(server_socket, 1);

    FD_ZERO(&allfd);    
    FD_SET(server_socket, &allfd); 
    FD_SET(0, &allfd);
    printf("\n*******Chatroom Server*******");
    while(1){
        modfd = allfd;
        select(FD_SETSIZE, &modfd, NULL, NULL, NULL);

        for(temp = 0; temp < FD_SETSIZE; temp++) {
            if(FD_ISSET(temp, &modfd)) {
                switch(temp){
                    case 0:
                        break;
                    default:
                        if(temp == server_socket){
                            chat_socket = accept(server_socket, NULL, NULL);
                        }
                        else{
                            char msg_buf[MSG_SIZE];
                            char buf[MAX_LOAD];
                            char name[MAX_LOAD];

                            struct msg temp_message;
                            struct chat_room* local_chat = NULL;

                            void* (*init_chatroom)() = &chat_room_main;
                            void* thread_args;

                            pthread_attr_t attr;
                            pthread_t tid;

                            pthread_attr_init(&attr);
                            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

                            memset(buf, 0, sizeof(buf));
                            memset(msg_buf, 0, sizeof(msg_buf));
                            msg_buf[19]= 0;

                            int read_val = read(temp, msg_buf, MSG_SIZE);
                            if(read_val > 0){
                                memcpy(&temp_message, msg_buf, sizeof(temp_message));
                                read(temp, buf, temp_message.length - sizeof(temp_message));
                                memcpy(name, buf, temp_message.length - sizeof(temp_message));

                                if(temp_message.type == 0) {//if create
                                    local_chat = addRoom(temp, name, chatrooms);

                                    if(local_chat != NULL){
                                        thread_args = (void*)malloc(sizeof(struct chat_room));
                                        memcpy((struct chat_room*) thread_args, local_chat, sizeof(struct chat_room));
                                        pthread_create(&tid, &attr, init_chatroom, thread_args);
                                        local_chat->id = tid;
                                        createResponse(temp, local_chat->port, 10);
                                    }

                                }
                                else if(temp_message.type == 1){ //join
                                    local_chat = joinServer(temp, name, chatrooms);

                                    if(local_chat != NULL){
                                        joinResponse(temp, local_chat->port);
                                    }

                                }
                                else if(temp_message.type == 2){ //delete
                                    local_chat = findRoom(name, chatrooms);

                                    printf("Deleting Room\n");
                                    if(local_chat != NULL) {
                                        local_chat->port = 0;
                                        close(local_chat->socket_d);
                                        deleteResponse(temp, local_chat);

                                        for(j = 0; j<MAX_CRC; j++){
                                            if(local_chat->clients[j]!=0) {
                                                FD_CLR(local_chat->clients[j], &modfd);
                                                local_chat->clients[j] = 0;
                                            }
                                        }
                                        pthread_cancel(local_chat->id);
                                    }
                                }

                            }
                            else if(read_val <= 0){
                                FD_CLR(temp, &allfd);

                                close(temp);
                            }
                        }
                }
            }
        }
    }

    return 0;

}

Client.c

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

#define PORT_NUM 12333
#define MSG_SIZE 8
#define MAX_LOAD 246
#define MAX_BUF 256
#define SERVER_IP 32

struct msg {
    int type;
    int length;
};

struct thread_para {
    int port;
    struct hostent* host_name;

};

int sendCmd(int chat_socket, char* buf, int type){ //function for sending the command
    struct msg temp;
    char temp_buf[MAX_LOAD];
    char name[MAX_LOAD];

    int iterator;

    if(type == 0){
        iterator = 6;
    }
    else if(type == 1){
        iterator = 4;
    }
    else if(type == 2){
        iterator = 6;
    }

    for(; iterator < strlen(buf); iterator++){
        if(buf[iterator] == ' ') {
            continue;
        }   
        else{
            break;
        }
    }

    strcpy(name, buf+iterator);
    memset(temp_buf, 0, MAX_LOAD);
    temp.type = type;
    temp.length = sizeof(temp)+strlen(name)+1;  //for \0


    memcpy(temp_buf, &temp, sizeof(temp));
    memcpy(temp_buf+sizeof(temp), name, strlen(name)+1);

    write(chat_socket, temp_buf, temp.length);

    return 0;

}

void* connectChat(int port_num, struct hostent* host_name, int master){
    char buf[MAX_BUF];
    char temp_buf[MAX_BUF];

    int chat_socket;
    int i;
    int input;
    int temp; //temp fd

    fd_set allfd, modfd;

    struct sockaddr_in sock;

    printf("Successfully Joined Room\n");
    memset(buf, 0, sizeof(buf));
    memset(&sock, 0, sizeof(sock));
    sock.sin_family = AF_INET;
    sock.sin_port   = htons(port_num);
    memcpy((char*)&sock.sin_addr.s_addr, host_name->h_addr, host_name->h_length);

    chat_socket = socket(AF_INET, SOCK_STREAM, 0);
    if(chat_socket == -1){
        perror("Error in creation");
        return NULL;
    }

    if(connect(chat_socket, (struct sockaddr*)&sock, sizeof(struct sockaddr)) < 0 ){
        perror("Error in connection");
        return NULL;
    }

    FD_ZERO(&allfd);        
    FD_SET(chat_socket, &allfd);    
    FD_SET(0, &allfd);     
    FD_SET(master, &allfd);

    while(1) {
        modfd = allfd;
        select(FD_SETSIZE, &modfd, NULL, NULL, NULL);

        for(temp = 0; temp< FD_SETSIZE; temp++){

            memset(buf, 0, sizeof(buf));
            memset(temp, 0, sizeof(buf));

            if(temp == 0) { //reading from standard in
                input = read(0, buf, MAX_BUF);
                buf[input-1] = '\0'; //add termination to end
                write(chat_socket, buf, strlen(buf));

            }
            else if(temp == chat_socket){
                input = read(0, buf, MAX_BUF);
                buf[input] = '\0';

                memcpy(temp, buf, input);
                //display message
                printf("%s \n", temp_buf);
            }
            else if(temp == master){
                struct msg temp_message;
                input = read(temp, buf, MSG_SIZE);
                memcpy(&temp_message, buf, MSG_SIZE);
                if(temp_message.type == 12){
                    printf("Chatroom has been deleted, Shutting down chatroom\n");
                    return NULL;
                }
            }
        }
    }

    return 0;
}

int main(int argc, char* argv[]){

    char buf[MAX_BUF];

    int chat_socket;
    int i;
    int input;
    int temp; //temp fd
    int accept_input = 1;  // take input for stdin to create a chat thread

    fd_set allfd, modfd;

    char server_ip[SERVER_IP];
    struct hostent* host_name;
    struct sockaddr_in sock;


    struct msg temp_message;

    pthread_attr_t tattr;
    pthread_t tid;

    if(argc < 2) {
        printf("Please try ./crc <server IP> \n");
        return -1;
    }

    pthread_attr_init(&tattr);
    pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);

    memset(&sock, '\0', sizeof(sock));
    sock.sin_family = AF_INET;
    sock.sin_port   = htons(PORT_NUM);
    strcpy(server_ip ,argv[1]);


    if((host_name = (struct hostent*)gethostbyname(server_ip)) ==  NULL){
        perror("failed to get host name");
        return -1;
    }

    memcpy((char*)&sock.sin_addr.s_addr, host_name->h_addr, host_name->h_length);

    chat_socket = socket(AF_INET, SOCK_STREAM, 0);
    if(chat_socket == -1){
        perror("Error creating socket");
        return -1;
    }

    if((connect(chat_socket, (struct sockaddr*)&sock, sizeof(sock))) < 0) {
        perror("Error connecting");
        return -1;
    }

    FD_ZERO(&allfd);        /* first, clear the allfd set */
    FD_SET(chat_socket, &allfd);    /* adding client to the set */
    FD_SET(0, &allfd);  
    printf("*****Welcome to the Chatroom*****\n");

    while(1){
        modfd = allfd;
        select(FD_SETSIZE, &modfd, NULL, NULL, NULL);

        for(temp = 0; temp < FD_SETSIZE; temp++){
            if(FD_ISSET(temp, &modfd)){

                if(temp == 0){


                    input = read(0, buf, MAX_BUF);
                    buf[input-1] = '\0';  //remove \n inserts termination

                    if((strncasecmp(buf, "create ", 7) == 0)) {
                        sendCmd(chat_socket, buf, 0);
                    }
                    else if((strncasecmp(buf, "join ", 5) == 0)) {
                        sendCmd(chat_socket, buf, 1);
                    }
                    else if((strncasecmp(buf, "delete ", 7)==0)){
                        sendCmd(chat_socket, buf, 2);
                    }
                    else
                    {
                        printf("Enter a valid command: create <Room_name>, join <Room_name>, delete <Room_name>\n");
                    }
                }
                else if(temp == chat_socket){
                    input = read(temp, buf, MSG_SIZE);
                    memcpy(&temp_message, buf, sizeof(temp_message));

                    if(temp_message.type == 10) {
                        printf("Created Chatroom\n");
                    }
                    else if(temp_message.type == 11){
                        connectChat(temp_message.length, host_name, chat_socket);
                            fflush(stdin);
                    }
                    else if(temp_message.type == 15) {
                        printf("Chatroom exits. Type join <Room_name> to join\n");
                    }
                }
            }
        }
    }

    close(chat_socket);
    return 0;
}

我提供了两组代码以防万一。该程序旨在创建多个聊天室。

2 个答案:

答案 0 :(得分:1)

invalid argumentEINVAL错误代码,在connect()的上下文中表示:

  

检测到无效参数(例如,address_len对地址系列无效,指定的地址系列无效)。

您的客户端代码中有多次调用connect()(为什么?),但您没有指出哪个调用是失败的调用。至少在connectChat()sizeof(struct sockaddr)应该是sizeof(struct sockaddr_in),或者更好sizeof(sock),就像在main()中一样。

此外,如果connect()失败,则表示您正在泄漏socket()返回的套接字。您需要close()

此外,不推荐gethostbyname(),您应该使用getaddrinfo()。您正在创建IPv4套接字,它仅适用于IPv4地址。在将地址字节复制到gethostbyname()变量之前,您不会检查host_name->h_addr_type == AF_INET是否实际返回IPv4地址(sock)。至少使用getaddrinfo(),您可以仅将输出限制为IPv4地址。您没有gethostbyname()的选项。

答案 1 :(得分:0)

由于您正在寻找找出错误的方法,我建议您使用以下ng-pattern

Makefile

运行CFLAGS=-Wall -g -O2 CC=gcc LDFLAGS=-lpthread all: Server Client Server: Server.c Client: Client.c 命令后,您会看到很多警告。其中一些:

make

所以试着修复这些警告。我的意思是所有这些