0

..when I run:

gcc -o server -lpthread server.c

the error happened. and:

gcc -o client -lpthread client.c

the same error again.

I am writing a TCP-based chatroom program。

There is server.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
int sockfd;//客户端socket
char* IP = "192.168.255.255";//服务器的IP
short PORT = 8000;//服务器服务端口
typedef struct sockaddr SA;
char name[30];
void init(){
    sockfd = socket(PF_INET,SOCK_STREAM,0);
    struct sockaddr_in addr;//服务器端
    addr.sin_family = PF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = inet_addr(IP);
    if (connect(sockfd,(SA*)&addr,sizeof(addr)) == -1){
        perror("无法连接到服务器");
        exit(-1);
    }
    printf("客户端启动成功\n");
}
void start(){
    pthread_t id;
    void* recv_thread(void*);//声明了一个空指针
    pthread_create(&id,0,recv_thread,0);
    char buf2[100] = {};
    sprintf(buf2,"%s进入了聊天室",name);
    send(sockfd,buf2,strlen(buf2),0);
    while(1){
        char buf[100] = {};
        scanf("%s",buf);//消息内容
        char msg[131] = {};
        sprintf(msg,"%s:%s",name,buf);
        send(sockfd,msg,strlen(msg),0);
        if (strcmp(buf,"bye") == 0){//strcmp :字符串比较函数
            memset(buf2,0,sizeof(buf2));//void *memset(void *__s, int __c, size_t __n),复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符。
            sprintf(buf2,"%s退出了聊天室",name);
            send(sockfd,buf2,strlen(buf2),0);
            break;
        }
    }
    close(sockfd);
}
void* recv_thread(void* p){
    while(1){
        char buf[100] = {};
        if (recv(sockfd,buf,sizeof(buf),0) <= 0){
            return 0;
        }
        printf("%s\n",buf);
    }
}
int main(){
    init();
    printf("请输入您的名字:");
    scanf("%s",name);
    start();
    return 0;
}

I really don't know what happend.

It perplexs me so long!!! Help me please!!!

Gewure
  • 1,208
  • 18
  • 31
  • 1
    Also, the usuals: failure to correctly and completely handle the results returned from system calls like send(), recv(). Failure to correctly use library calls that require a NUL-terminated char array. – Martin James Apr 19 '20 at 19:38
  • int main (int argc, char* argv[]) is the common header of a main function in C – Gewure Apr 19 '20 at 23:01

2 Answers2

0

Order matters, use

gcc -o server server.c -lpthread
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
0

I found a solution to the problem, which seems to be due to the code specification. When I add blank lines between all defined functions (including the main function, of course), I think this should be the key to the problem. Help gcc find the exact definition of the main function), and compile the link again. The new version server.c (just add the blank line):

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

int sockfd;//服务器socket
int fds[100];//客户端的socketfd,100个元素,fds[0]~fds[99]
int size =100 ;//用来控制进入聊天室的人数为100以内
char* IP = "192.168.255.255";
short PORT = 8000;
typedef struct sockaddr SA;

int pthread_create(
                 pthread_t *restrict tidp,   //新创建的线程ID指向的内存单元。
                 const pthread_attr_t *restrict attr,  //线程属性,默认为NULL
                 void *(*start_rtn)(void *), //新创建的线程从start_rtn函数的地址开始运行
                 void *restrict arg //默认为NULL。若上述函数需要参数,将参数放入结构中并将地址作为arg传入。
                  );

void init(){
    sockfd = socket(PF_INET,SOCK_STREAM,0);
    if (sockfd == -1){
        perror("创建socket失败");
        exit(-1);
    }
    struct sockaddr_in addr;
    addr.sin_family = PF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = inet_addr(IP);
    if (bind(sockfd,(SA*)&addr,sizeof(addr)) == -1){
        perror("绑定失败");
        exit(-1);
    }
    if (listen(sockfd,100) == -1){
        perror("设置监听失败");
        exit(-1);
    }
}

void SendMsgToAll(char* msg){
    int i;
    for (i = 0;i < size;i++){
        if (fds[i] != 0){
            printf("sendto%d\n",fds[i]);
            send(fds[i],msg,strlen(msg),0);
        }
    }
}

void* service_thread(void* p){
    int fd = *(int*)p;
    printf("pthread = %d\n",fd);
    while(1){
        char buf[100] = {};
        if (recv(fd,buf,sizeof(buf),0) <= 0){//阻塞与非阻塞recv返回值没有区分,都是 <0 出错 =0 连接关闭 >0 接收到数据大小
            int i;
            for (i = 0;i < size;i++){
                if (fd == fds[i]){//遍历寻找那个关闭的连接
                    fds[i] = 0;
                    break;
                }
            }
                printf("退出:fd = %dquit\n",fd);
                pthread_exit((void*)&i);
        }
        //把服务器接受到的信息发给所有的客户端
        SendMsgToAll(buf);
    }
}

void service(){
    printf("服务器启动\n");
    while(1){
        struct sockaddr_in fromaddr;
        socklen_t len = sizeof(fromaddr);
        int fd = accept(sockfd,(SA*)&fromaddr,&len);
        if (fd == -1){
            printf("客户端连接出错...\n");
            continue;
        }
        int i = 0;
        for (i = 0;i < size;i++){
            if (fds[i] == 0){
                //记录客户端的socket
                fds[i] = fd;
                printf("fd = %d\n",fd);
                //有客户端连接之后,启动线程给此客户服务
                pthread_t tid;
                pthread_create(&tid,0,service_thread,&fd);
                break;
            }
        if (size == i){
            //发送给客户端说聊天室满了
            char* str = "对不起,聊天室已经满了!";
            send(fd,str,strlen(str),0); 
            close(fd);
        }
        }
    }
}

int main(){
    init();
    service();
    return 0;
}

and then:

gcc -o server server.c -plthread

it can work. By the way, I use vscode to add a new .c file. After add blank lines, the .c flie is recognized as a C file. It has a huge C on its icon ofter adding blank lines. just like this

  • 1
    There are a lot of problems still. The system call returns incompletely handled, how you pass the fd to the thread, (it's not safe to pass the address of a local that may be overwritten or disappear before the thread can dereference it), the strlen call in SendMsgToAll, (buf not guaranteed NUL-terminated). – Martin James Apr 20 '20 at 06:34
  • Can you be more specific? Because I know little about multithreading,thank you very much! – jessic wang Apr 20 '20 at 07:35