免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2442 | 回复: 9
打印 上一主题 下一主题

多线程连接服务器的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-09 14:03 |只看该作者 |倒序浏览
写了一个程序,目的是用4个线程同时连接服务器,其中 connect_thread 函数负责连接服务器,
它调用gethostbyname来寻址,如果对 connect _thread 启动4个线程,同时连接服务器,竟然
没有一个线程可以连接成功,但如果不用线程,只调用 connect_thread函数4次,那么每次
调用都可以成功连接到服务器。
  为什么多线程连接会失败呢?大家帮我看看啊
#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <pthread.h>

void *connect_thread(void *arg);        /* 连接服务器 */

int main() {
        pthread_t tid[4];       /* 4个线程的ID */
        int i;
        int clientfd[4];     /* 4次连接到服务器的套接字 */
        void *tret;

        for (i = 0; i < 4; i++) {
                pthread_create(tid+i, NULL, connect_thread, clientfd + i);    /* 线程的方式 */
                //connect_thread(clientfd + i);                               /* 函数调用的方式 */

        }
}

void *connect_thread(void *arg) {
        struct hostent *host = NULL;
        struct sockaddr_in addr;
        struct sockaddr_in local;
        int *clientfd = (int *)arg;

        *clientfd = socket( AF_INET, SOCK_STREAM, 0 );
        host = gethostbyname( "62.duote.com" ); /* 问题就出在这里,多线程调用这个函数貌似有问题 */

        printf("clientfd = %dn", *clientfd);   /* 打印此次连接的套接字 */

        addr.sin_family = AF_INET;
        addr.sin_port = htons( 80 );
        addr.sin_addr = *( (struct in_addr *) host->h_addr );

        connect( *clientfd, (struct sockaddr *) &addr, sizeof( struct sockaddr_in ));
}


[ 本帖最后由 kenby 于 2009-4-10 08:13 编辑 ]

src.tar.gz

764 Bytes, 下载次数: 39

论坛徽章:
0
2 [报告]
发表于 2009-04-09 14:34 |只看该作者
这个函数返回的地址是static变量,因此不需要你取释放,也一次非线程安全

论坛徽章:
0
3 [报告]
发表于 2009-04-09 14:36 |只看该作者
原帖由 r2r4 于 2009-4-9 14:34 发表
这个函数返回的地址是static变量,因此不需要你取释放,也一次非线程安全

那如何解决呢?

论坛徽章:
0
4 [报告]
发表于 2009-04-09 15:07 |只看该作者
mutex,每次线程访问前先取得个锁
然后最好线程自己copy一份,立刻释放锁

论坛徽章:
0
5 [报告]
发表于 2009-04-09 15:19 |只看该作者
gethostbyname有个线程安全版的

论坛徽章:
0
6 [报告]
发表于 2009-04-09 15:26 |只看该作者
原帖由 net_robber 于 2009-4-9 15:19 发表
gethostbyname有个线程安全版的

那一定是gethostbyname_r 属于(/* GNU extensions */)
有的系统不提供

论坛徽章:
0
7 [报告]
发表于 2009-04-10 08:14 |只看该作者
问题还没解决

论坛徽章:
0
8 [报告]
发表于 2009-04-10 09:32 |只看该作者
62.duote.com 是服务器地址,不必每次连接都解析一遍

论坛徽章:
0
9 [报告]
发表于 2009-04-10 13:47 |只看该作者
int *clientfd = (int *)arg;

        *clientfd = socket( AF_INET, SOCK_STREAM, 0 );

这里,你申明 client的socketfd用的竟然是指针,你所有的线程都用同一个socketfd?
这样你每启动一个进程,就会改写socketfd,
直接int clientfd 不要用指针。

[ 本帖最后由 墨小白 于 2009-4-10 13:49 编辑 ]

论坛徽章:
0
10 [报告]
发表于 2009-04-11 02:18 |只看该作者
原帖由 qsc555 于 2009-4-10 09:32 发表
62.duote.com 是服务器地址,不必每次连接都解析一遍

醍醐灌顶阿,改成这样就行了
#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <pthread.h>

struct hostent *host = NULL;
struct sockaddr_in addr;

void *connect_thread(void *arg);        /* 连接服务器 */

int main() {
        pthread_t tid[4];       /* 4个线程的ID */
        int i;
        int clientfd[4];     /* 4次连接到服务器的套接字 */

        host = gethostbyname( "62.duote.com" );   
        addr.sin_family = AF_INET;
        addr.sin_port = htons( 80 );
        addr.sin_addr = *( (struct in_addr *) host->h_addr );

        for (i = 0; i < 4; i++) {
                pthread_create(tid+i, NULL, connect_thread, clientfd + i);    /* 线程的方式 */
                //connect_thread(clientfd + i);                               /* 函数调用的方式 */


        }
}

void *connect_thread(void *arg) {
        int *clientfd = (int *)arg;

        *clientfd = socket( AF_INET, SOCK_STREAM, 0 );
        printf("clientfd = %dn", *clientfd);   /* 打印此次连接的套接字 */
        connect( *clientfd, (struct sockaddr *) &addr, sizeof( struct sockaddr_in ));
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP