免费注册 查看新帖 |

Chinaunix

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

多线程之间共享socket问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-12-24 23:58 |只看该作者 |倒序浏览
最近想用Win32::GUI聊天客户端软件.
当成功登录服务器后,派生出一个线程,用来专门收数据,主线程用来发送数据.
以下是节选出的主要代码,里面可能缺少了某些工具方法.

#!c:\perl\bin\perl.exe -w

use strict;
use Win32::GUI;
use threads;
use threads::shared;

use PerlChat::Chat;
use PerlChat::Config;
use PerlChat::Utils;

#初始化聊天类

my $config = getConfig("conf/config.conf");
my $chat = PerlChat::Chat->spawn($config->{ip},$config->{port});

my $mainWin = new Win32::GUI::Window(
    -name        => 'mainWin',
    -text        => '51GG',
    -size        => [ $s_Main->{w}, $s_Main->{h} ],
    -onResize    => \&mainWinResize,
    -onMinimize  => sub { 1 },
    -onMaximize  => sub { 1 },
    -onTerminate => \&mainWinClose,
);

$mainWin->AddTextfield(
    -name   => 'Username',
    -pos    => [ $s_Login->{x} + 55, $s_Login->{y} + 20 ],
    -size   => [ 120, 20 ],
    -prompt => [ "用户名:", -45 ],
);

$mainWin->AddTextfield(
    -name   => 'Password',
    -pos    => [ $s_Login->{x} + 55, $s_Login->{y} + 40 ],
    -size   => [ 120, 20 ],
    -password => 1,
    -prompt => [ "密  码:", -45 ],
);

$mainWin->AddButton(
    -name  => 'LoginServer',
    -pos   => [ $s_Login->{x} + 50, $s_Login->{y} + 70 ],
    -title => '登录',
    -onClick => \&LoginServer,
);

$mainWin->AddButton(
    -name  => 'LogoutServer',
    -pos   => [ $s_Login->{x} + 100, $s_Login->{y} + 70 ],
    -title => '注销',
    -disabled => 1,
    -onClick => \&LogoutServer,
);

#主循环

$mainWin->Show();

Win32::GUI::Dialog();

sub LoginServer{
    $chat = PerlChat::Chat->spawn($config->{ip},$config->{port}) unless ($chat->{dp});
    my ($username,$password) = ($mainWin->{Username}->Text(),$mainWin->{Password}->Text());
    my $loginStr = makeLoginStr($username,$password);
    $mainWin->MessageBox('登录信息发送失败,请重新启动本程序,点击"确定"关闭本程序','错误',MB_OK | MB_ICONERROR) and return -1 unless ($chat->send_data($loginStr) == 0);

    my $ret = $chat->recv_data(1);
    $mainWin->MessageBox('系统繁忙,登录失败,请重新启动本程序,点击"确定"关闭本程序','错误',MB_OK | MB_ICONERROR) and return -1 unless ($ret == 1);
    
    my $threadRecvMsg = threads->create(sub {$chat->recv_data($mainWin);});
    $threadRecvMsg->detach();
}

sub LogoutServer
{
    my $logoutStr = "~2~" . $chat->{'uin'} . "~100~200~1~0~0";
    $logoutStr = ( length($logoutStr) - 1 ) . $logoutStr;
    $chat->{'dp'}
      ->send_data( $chat->{'sock'},$logoutStr);
    $chat->{'dp'}->close_socket( $chat->{'sock'} );
}

__END__


但是遇到一个问题是,当派生出一个新线程后,就只能收数据了,主线程不能发数据了.因为收数据和发数据需要共用一个socket,我把这个socket存在一个聊天对象中.
这时候就有个在不同线程间共享socket的问题.
我用threads::shared模块的share方法来共享数据,
在程序的最开始想直接共享$chat这个对象.但是同样只能收不能发.
我尝试在login方法中加入只对$chat->{'socket'}共享,但是Perl提示:Cannot share globs yet.


不知道我有没有描述清楚,我估计原因可能是socket没有共享.所以导致只能收不能发.
请问这种情况应该怎样解决.谢谢.
如果我哪个地方没有描述清楚我会补上.

论坛徽章:
0
2 [报告]
发表于 2007-12-25 00:00 |只看该作者
补充一点:
sub LoginServer{
    $chat = PerlChat::Chat->spawn($config->{ip},$config->{port}) unless ($chat->{dp});
    my ($username,$password) = ($mainWin->{Username}->Text(),$mainWin->{Password}->Text());
    my $loginStr = makeLoginStr($username,$password);
    $mainWin->MessageBox('登录信息发送失败,请重新启动本程序,点击"确定"关闭本程序','错误',MB_OK | MB_ICONERROR) and return -1 unless ($chat->send_data($loginStr) == 0);

    my $ret = $chat->recv_data(1);
    $mainWin->MessageBox('系统繁忙,登录失败,请重新启动本程序,点击"确定"关闭本程序','错误',MB_OK | MB_ICONERROR) and return -1 unless ($ret == 1);
    
    my $threadRecvMsg = threads->create(sub {$chat->recv_data($mainWin);});
    $threadRecvMsg->detach();
}



从上面这个方法应该可以说明
$chat->send_data()和$chat->recv_data()方法是工作正常的.
所以我想问题不是卡在收发数据的方法上.因为我能接收到登录后返回的数据包.

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
3 [报告]
发表于 2007-12-25 00:43 |只看该作者
建议你用 POE。
POE 可以用单线程解决一切问题。

论坛徽章:
0
4 [报告]
发表于 2007-12-25 09:10 |只看该作者
呵呵,昨晚想到了POE可能可以解决,但是还没怎么用过,今天试试看。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP