您的位置:程序门 -> vc/mfc -> 网络编程



关于udp 完成端口的问题


[收藏此页] [打印本页]选择字色:背景色:字体:[][][]


关于udp 完成端口的问题
发表于:2008-01-25 12:43:44 楼主
我做了一个udp的服务器采用完成端口的方式,我在wsarecv后可以通过getqueuedcompletionstatus得到一个完成事件,这时我对得到的数据进行处理,但是我想用通过接受的内容将数据wsasend到发送方,就会出现10057错误,主要是由于套接字没有连接并且(当使用一个   sendto   调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。我想问的是如何通过完成端口方式可以得到发送的一些信息:比如发送方的在服务器的端口信息。
发表于:2008-01-25 12:45:391楼 得分:0
使用wsarecvfrom/wsasendto
wsarecvfrom当中就有对方的地址和端口,此时wsasendto就可以使用之。
发表于:2008-01-25 12:48:292楼 得分:0
但是我通过wsarecvfrom以后投递接收,然后getqueuedcompletionstatus给我的数据信息中也没有客户端的端口信息!
发表于:2008-01-25 13:00:173楼 得分:0
在线等!
发表于:2008-01-25 13:09:494楼 得分:0
wsarecvfrom当中的后面两个出参,也需要动态申请内存,不可以使用栈内存。
发表于:2008-01-25 13:10:175楼 得分:0
也就是address和addresslength
发表于:2008-01-25 13:37:376楼 得分:0
bool   ccommunication::initnetwork(bool   btcp,   bool   budp,   int   itcpport,   int   iudpport)
{
::initializecriticalsection(&m_csection);
m_btcptype   =   btcp;
m_budptype   =   budp;
m_itcpport   =   itcpport;
m_iudpport   =   iudpport;
cstring strerror;
                if   (   m_budptype   )
{
m_sudpsever   =   createsever(udp);
if   (   m_sudpsever   ==   invalid_socket   )
{
return   false;
}

m_hudpcompletionport   =   createiocompletionport(invalid_handle_value,   null,   0,   0);
if   (   m_hudpcompletionport   ==   null   )
{
m_dwerror   =   getlasterror();
strerror.format("%d",   m_dwerror);
closehandle(m_htcpcompletionport);
afxmessagebox("create   udp   io   completion   port   fail,   error:"   +   strerror);
return   false;
}
char   szname[_max_path];
cstring   str;
int   err   =   gethostname(szname,   _max_path);
if   (   err   ==   socket_error   )
{
str.format("%d",   wsagetlasterror());
}
hostent   *phostent   =   gethostbyname(szname);
if   (   phostent   ==   null   )
{
afxmessagebox("communication   gethostbyname   error");
return   false;
}
in_addr   addr;
memcpy(&addr,   phostent-> h_addr_list[0],   sizeof(in_addr));
system_info   sysinfo;
getsysteminfo(&sysinfo);
for   (   int   i   =   0;   i   <   1/*sysinfo.dwnumberofprocessors*2+2*/;   i++)
{
dword   workerthreadforudpid;
handle   hworkerthreadforudp   =   createthread(null,
  0,
  &workerforudpproc,
  this,
  0,
  &workerthreadforudpid);
if   (   hworkerthreadforudp   ==   null   )
{
m_dwerror   =   getlasterror();
strerror.format("%d",   m_dwerror);
closehandle(hworkerthreadforudp);
afxmessagebox("create   workerthreadforudp   thread   fail,   error:"   +   strerror);
return   false;
}
closehandle(hworkerthreadforudp);
}

lpperhandledata   perhandledataforudp   =   (lpperhandledata)globalalloc(gptr,   sizeof(perhandledata));
sockaddr_in   addrfrom;
int   isize   =   sizeof(addrfrom);
                                createiocompletionport((handle)m_sudpsever,
m_hudpcompletionport,
(dword)&addrfrom,
0);
dword   recvbytes,   flag   =   0;
lpperiohandledata   periohandledataforudp   =   (lpperiohandledata)globalalloc(gptr,   sizeof(periohandledata));
memset(&(periohandledataforudp-> overlap),   0,   sizeof(overlapped));
periohandledataforudp-> recvdatabuf.buf   =   periohandledataforudp-> recvbuf;
periohandledataforudp-> recvdatabuf.len   =   pocket_default_size;
periohandledataforudp-> itype   =   recv_data;
                               
err   =   wsarecvfrom(m_sudpsever,
    &(periohandledataforudp-> recvdatabuf),
    1,
    &recvbytes,
    &flag,
    (sockaddr*)&addrfrom,
    &isize,
    &(periohandledataforudp-> overlap),
    null);
if   (   err   ==   socket_error   )
{
str.format("%d",   wsagetlasterror());
}
}
return   true;
}
dword   winapi   workerforudpproc(lpvoid   lparam)
{
int   err;
cstring   strerr;
ccommunication*   pcommunication   =   (ccommunication*)lparam;

lpperhandledata   perhandledata;
sockaddr_in   addr;
lpperiohandledata   periohandledata;
dword   dwrecvbyte   =   0;
while   (true)
{
bool   bsuccess   =   getqueuedcompletionstatus(pcommunication-> getudpcompletionport(),
    &dwrecvbyte,
    (lpdword)&addr,
    (lpoverlapped*)&periohandledata,
    infinite);
if   (   dwrecvbyte   ==   -1   &&   perhandledata   ==   null   )
{
return   1l;
}

if   (   dwrecvbyte   !=   0   &&   periohandledata-> itype   ==   recv_data   )
{
pcommunication-> dealdatafromudpcomletionport(perhandledata,   periohandledata,   dwrecvbyte);
dword   dwflag   =   0;
memset(periohandledata-> sendbuf,   0,   pocket_default_size);
memcpy(periohandledata-> sendbuf,   periohandledata-> recvbuf,   pocket_default_size);
periohandledata-> itype   =   send_data;
periohandledata-> senddatabuf.buf   =   periohandledata-> sendbuf;
periohandledata-> senddatabuf.len   =   periohandledata-> recvdatabuf.len;
memset(periohandledata-> recvbuf,   0,   pocket_default_size);
memset(&periohandledata-> overlap,   0,   sizeof(overlapped));
err   =   wsasendto(pcommunication-> getudpseversocket(),
            &(periohandledata-> senddatabuf),
            1,
            &dwrecvbyte,
            dwflag,
                                                                            (sockaddr*)&addrfrom,
            sizeof(sockaddr),
            &(periohandledata-> overlap),
            null);
if   (   err   ==   socket_error   )
{
strerr.format("%d",   wsagetlasterror());
}
}
else   if   (   dwrecvbyte   ==   0   &&   ((periohandledata-> itype   ==   recv_data)   ¦ ¦   (periohandledata-> itype   ==   send_data))   )
{
//delete   client
}
}
return   1l;
}
我是这样写的,不知道哪里错掉了。
发表于:2008-01-25 13:45:477楼 得分:0
我只有服务器是完成端口模式,客户端不是不知道是不是这个原因呢?
发表于:2008-01-25 14:01:538楼 得分:0
完成端口只是一种实现,不影响协议,跟对端使用什么技术没有任何关系。

看到你贴出来的代码,我感觉前面我说的全是废话。
发表于:2008-01-25 17:35:559楼 得分:0
to   unsigned:
看到你贴出来的代码,我感觉前面我说的全是废话


为什么是废话???
发表于:2008-01-25 22:17:4510楼 得分:0
因为   unsigned   很生气,所以后果很严重。哈哈,开个玩笑。

unsigned   说得对,要得到客户端的地址,是通过   wsarecvfrom   的参数,也就是   address   和   addresslength。你是知道使用了getqueuedcompletionstatus,可能还没有深刻理解。此函数返回的单句柄数据结构需要重新定义一下,包含客户地址成员,投递   wsarecvfrom   函数时把使用单句柄数据的客户地址成员作为输入参数,在   getqueuedcompletionstatus   返回的单句柄数据中就自然包含了客户端的地址。供参考。

  unsigned   我说得对吗?
发表于:2008-01-28 09:24:4011楼 得分:0
首先,udp当中跟tcp不一样,由于后者是确定在某个连接上的,wsarecv的地址也就被确定了,而前者由于是一个未知的地址,如果你需要进行双向通讯,那么就需要得到该地址,但是在wsarecv当中并没有参数可以返回相关的地址,所以需要替换成wsarecvfrom;
然后,wsarecvfrom当中的地址和地址长度,都是出参,需要交给系统去改写,那么这个地址,就需要动态分配,否则系统会写入到一个野指针当中,后果难以想象。同样的,既然使用的是一个动态分配的内存空间,那么这个指针就需要保存,更何况后面通讯的时候还需要用到,最好的办法是放到overlapped的扩展结构当中去。


快速检索

最新资讯
热门点击