我看了一些博客,多线程网络编程用的是堵塞,也就是 pthread_join 函数,可是既然是监听接口怎么能用堵塞的。

我要做的东西是:监听80端口,然后接收请求,创建一个线程完成相应任务。

我遇到的问题是:用阻塞(也就是pthread_join(thread_id))相当于单线程无法满足要求,用非阻塞(pthread_detach(thread_id))然后我的socket没反应。

问题原因:在一个循环中创建的Socket,如果socket的id是局部变量那么当前循环结束后,该变量的空间就会被回收掉,导致进入线程函数之后,获取不到socket的id的值。

解决方法:用malloc申请一个int的空间存储socket的id,然后在线程中释放这片空间。

接下来放错误代码和成功代码:

错误代码1:(不算错误,只是用了阻塞,创建的线程未执行完之前不会创建其他线程)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>
#define SERVER_PORT 80
void aligenie_thread(void *tSock);

int main(void)
{
    int sock;
    struct sockaddr_in server_addr;
    sock = socket(AF_INET,SOCK_STREAM,0);
    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(SERVER_PORT);
    bind(sock,(struct sockaddr *)&server_addr,sizeof(server_addr));
    listen(sock,128);//监听
    printf("waiting for t's connect\n");
    int i = 0;
    while(1)
    {
        struct sockaddr_in tmall;
        int tSock = 0;//注意三个程序中这里的区别
        int tmall_addr_len = sizeof(tmall);
        tmall_addr_len = sizeof(tmall);
        tSock = accept(sock,(struct sockaddr *)&tmall,&tmall_addr_len);//接收到请求
        if(tSock<0)
        {
            close(tSock);
            continue;
        }
        pthread_t id;
        int ret;
        ret = pthread_create(&id,NULL,(void *)aligenie_thread,(void *)&tSock);//创建线程
        if(ret != 0)
        {
            printf(" Creat pthread error!\n");
        }
        printf("\nthread %d !\n",i++);
        pthread_join(id,NULL);//线程是阻塞的
    }
    return 0;
}
void aligenie_thread(void *tSock)
{
    int tmSock =*((int*)tSock);//获取socket的id
    write(tmSock,"hello world",strlen("hello world"));
    close(tmSock);
    pthread_exit(NULL);
}
                        

错误代码2:(虽然是非阻塞的,但是socket的id进入线程后空间马上就被回收了)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>
#define SERVER_PORT 80
void aligenie_thread(void *tSock);

int main(void)
{
    int sock;
    struct sockaddr_in server_addr;
    sock = socket(AF_INET,SOCK_STREAM,0);
    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(SERVER_PORT);
    bind(sock,(struct sockaddr *)&server_addr,sizeof(server_addr));
    listen(sock,128);//监听
    printf("waiting for t's connect\n");
    int i = 0;
    while(1)
    {
        struct sockaddr_in tmall;
        int tSock = 0;//注意三个程序中这里的区别
        int tmall_addr_len = sizeof(tmall);
        tmall_addr_len = sizeof(tmall);
        tSock = accept(sock,(struct sockaddr *)&tmall,&tmall_addr_len);//接收到请求
        if(tSock<0)
        {
            close(tSock);
            continue;
        }
        pthread_t id;
        int ret;
        ret = pthread_create(&id,NULL,(void *)aligenie_thread,(void *)&tSock);//创建线程
        pthread_detach(id);//线程非阻塞
        if(ret != 0)
        {
            printf(" Creat pthread error!\n");
        }
        printf("\nthread %d !\n",i++);
    }
    return 0;
}
void aligenie_thread(void *tSock)
{
    int tmSock =*((int*)tSock);//获取socket的id
    write(tmSock,"hello world",strlen("hello world"));
    close(tmSock);
    pthread_exit(NULL);
}
                        

正确的多线程:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>
#define SERVER_PORT 80
void aligenie_thread(void *tSock);

int main(void)
{
    int sock;
    struct sockaddr_in server_addr;
    sock = socket(AF_INET,SOCK_STREAM,0);
    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(SERVER_PORT);
    bind(sock,(struct sockaddr *)&server_addr,sizeof(server_addr));
    listen(sock,128);//监听
    printf("waiting for t's connect\n");
    int i = 0;
    while(1)
    {
        struct sockaddr_in tmall;
        int* tSock = (int *)malloc(sizeof(int));//注意三个程序中这里的区别
        int tmall_addr_len = sizeof(tmall);
        tmall_addr_len = sizeof(tmall);
        *tSock = accept(sock,(struct sockaddr *)&tmall,&tmall_addr_len);//接收到请求
        if(*tSock<0)
        {
            close(*tSock);
            continue;
        }
        pthread_t id;
        int ret;
        ret = pthread_create(&id,NULL,(void *)aligenie_thread,(void *)tSock);//创建线程
        pthread_detach(id);//线程非阻塞
        if(ret != 0)
        {
            printf(" Creat pthread error!\n");
        }
        printf("\nthread %d !\n",i++);
    }
    return 0;
}
void aligenie_thread(void *tSock)
{
    int tmSock =*((int*)tSock);//获取socket的id
    free(tSock);//在这里释放空间
    write(tmSock,"hello world",strlen("hello world"));
    close(tmSock);
    pthread_exit(NULL);
}
                        

记录:记得给socket的id分配空间,用完之后记得free掉

Logo

更多推荐