CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
IBM Rational 系统开发最佳实践工具包 WebSphere MQ 最佳实践 TOP 15
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  网络编程

多线程 网络应用, 帮忙看看, 谢谢!

楼主superdreamer(只懂一点点!)2006-03-06 18:12:14 在 VC/MFC / 网络编程 提问

要实现一个TFTP   SERVER,   我建立一个DLG   项目,   加一个BUTTON   ,   点击后创建一个线程,   线程函数就是建立一个SOCKET   并BIND在69   端口上,     然后就在那儿recvfrom(),启动后用TFTP   CLIENT对他发送或读取数据,   但SERVER返回值一直都是-1   ,   根本就没收到CLIENT的请求,   WHY?    
   
  问题点数:100、回复次数:12Top

1 楼DentistryDoctor(不在无聊中无奈,就在沉默中变态)回复于 2006-03-06 18:57:51 得分 10

还没有Client连接上?Top

2 楼orbit(走了走了)回复于 2006-03-06 19:06:10 得分 10

正常情况下recvfrom应该堵赛直到有client发送的sendto数据报到来,刻检查是不是这样,并检查recvfrom的返回值Top

3 楼nuaawenlin(飘人)回复于 2006-03-06 20:50:36 得分 10

把你的代码贴出来看看Top

4 楼nuaawenlin(飘人)回复于 2006-03-06 20:50:58 得分 10

使用WSAGetLastError看看错误信息是什么Top

5 楼oyljerry(【勇敢的心】→ ㊣提拉米苏√㊣)回复于 2006-03-06 21:31:51 得分 10

检查返回值等,看客户端是否正确连接Top

6 楼YufengShi(浪子)回复于 2006-03-06 22:33:42 得分 10

八成是client没找对server。Top

7 楼LongLongAgoImBoy(ThereIsAMe)回复于 2006-03-07 10:10:29 得分 40

用套接口实现UDP协议的网络通信  
   
  大连开发区捷通电脑技术  
  有限公司(116600)王淼  
  ----套接字是支持TCP/IP协议的网络通信的基本操作单元。可以将套接字看做不同主机间的进程进行双向通信的端点。在网络编程中最常用的方案便是客户机/服务器模型。本文主要讨论C/S模型下用套接口实现UDP协议的网络通信。利用Socket而自定义了CSockAddr类(与地址有关的机能都封装在这里)和CBlockingSocket类(里面封装了Socket),通过实践证明,通过使用这两个自定义类,可使应用程序非常简练、易读。  
   
  一、Socket类型  
  ----根据传输数据类型的不同,套接字可分为面向连接的字节流套接字(streamsockets)和无连接的数据报套接字(datagramsockets)两种类型。  
  ----1.字节流套接字  
   
  ----字节流不按记录定界,在TCP/IP协议簇中对应TCP协议,即传输控制协议。它是一个提供给用户进程可靠的全双工的面向连接的协议,大多数Internet应用程序如ftp、telnet使用TCP协议。  
   
  ----2.数据报套接字  
   
  ----数据报对应记录型数据流,在TCP/IP协议簇中对应UDP协议,即用户数据报协议(UserDatagramProtocol)。由于不建立连接,数据报协议比连接协议快。但不能保证所有数据都准确有序地到达目的地,不保证顺序性、可靠性和无重复性。它是无连接的服务,以独立的信包进行传输,通信端点使用UDP对应的Internet地址。双方不需互连,按固定的最大长度进行传输,因而适用于单个报文传输。  
   
  二、数据报套接字的工作过程  
  ----不论何种套接字编程,均采用客户机/服务器方式,数据报套分别生成服务进程和客户进程,在通信前必须创建各自的套接字以建立连接,然后对相应的套接字进行“读”“写”操作,实现信息的交换。如下图无连接协议的Socket编程模型。  
  服务器 客户机  
  socket() socket()  
      |     |  
  bind() bind()  
      |     |  
  recvfrom()     |  
      |<--------------------sendto()  
  处理服务请求     |  
      |  
  sendto()--------------->recvfrom()  
      |     |  
  close() close()  
   
  三、编程示例  
  ----利用SOCKET而自定义了CSockAddr类(与地址有关的机能都封装在里面)和CBlockingSocket类(里面封装了SOCKET),然后用VC++生成两个对话框工程,一个是服务器程序SV,另一个是客户端程序CL。实践证明,通过使用这两个自定义类,可使应用程序非常简练、易读。  
  ----以下是CSockAddr类和CBlockingSocket类这两个类的源程序。服务器程序SV和客户端程序CL只列出了相关的部分。  
   
  /***bsock.cpp:  
  **BlockSocketclass*/  
  //Socket地址类只跟AF_INET对应  
  //与地址有关的机能都在这里封装了。  
  typedefSOCKADDR*LPSOCKADDR;  
  classCSockAddr{  
   SOCKADDR_INm_SockAddrIN;  
  public:  
   CSockAddr(LPCSTRaddress=NULL,intport=0,  
  intfamily=AF_INET);//构造CSockAddr  
  //向LPSOCKADDR变换的运算  
   operatorLPSOCKADDR(void){return  
  (LPSOCKADDR)&m_SockAddrIN;}  
   intGetSize(void){returnsizeof(m_SockAddrIN);}  
  //IP情报的大小  
   BOOLIsIPAddress(LPCSTRaddress);  
  //IP地址的检查nnn.nnn.nnn.nnn  
  (n是[0-9])的形式检查  
   //IP地址的设定  
   voidSetIPAddrees(LPCSTRddress)  
  {m_SockAddrIN.sin_addr.s_addr=::inet_addr(address);}  
   //由主机名的IP地址的设定  
   BOOLSetIPAddressByHost(LPCSTRhostname)  
   {  
   structhostent*host=gethostbyname(hostname);  
   if(host==NULL){  
   TRACE(“SERVER%s没有找到code=  
  %d",hostname,WSAGetLastError());  
   returnFALSE;  
   }  
   m_SockAddrIN.sin_addr.s_addr=*(int*)host->h_addr;  
   returnTRUE;  
  }  
  //IP地址的文字的取得  
  CStringGetIPString(void)  
  {  
  CStringstr;  
  str.Format(“%d.%d.%d.%d",  
  m_SockAddrIN.sin_addr.S_un.S_un_b.s_b1,  
  m_SockAddrIN.sin_addr.S_un.S_un_b.s_b2,  
  m_SockAddrIN.sin_addr.S_un.S_un_b.s_b3,  
  m_SockAddrIN.sin_addr.S_un.S_un_b.s_b4  
  );  
  returnstr;  
  }  
   intGetPort(void){returnntohs(m_SockAddrIN.  
  sin_port);}//PORT的取得  
   voidDump(void)//DEBUG用  
  {  
   TRACE(“famiry=%d\n",m_SockAddrIN.  
  sin_family);  
   TRACE(“port=%d\n",ntohs(m_SockAddrIN.  
  sin_port));  
   TRACE(“addr=%s\n",GetIPString());  
  }  
  };  
  (未完)Top

8 楼LongLongAgoImBoy(ThereIsAMe)回复于 2006-03-07 10:10:50 得分 0

//CBlockingSocketclass  
  classCBlockingSocket{  
  protected:  
  public:  
  intm_BufferPointer;//1文字接受BUFFER  
  intm_BufferLength;  
  BYTEm_RecvBuffer[1024];  
  intm_ReceiveTimeout;//收数据TIMEOUT  
  //SOCKETHANDLE  
  SOCKETm_hSocket;  
  CBlockingSocket(void)//构造CBlockingSocket  
  {  
  m_ReceiveTimeout=INFINITE;  
  m_hSocket=INVALID_SOCKET;  
  m_BufferPointer=0;  
  m_BufferLength=0;  
  }  
  ~CBlockingSocket(void){}//DESTORY  
  //SCOKET的作成  
   BOOLSocket(intnSocketType=SOCK_STREAM,  
  intnProtocolType=IPPROTO_IP,intnAddressFormat=PF_INET);  
   BOOLBind(CSockAddr&addr)//SCOKET的绑定  
  {  
  if(bind(m_hSocket,addr,addr.GetSize())==  
  SOCKET_ERROR){  
  TRACE(“bind()error\n");  
  returnFALSE;  
  }else{  
  returnTRUE;  
  }  
  }  
  voidAttach(SOCKETsock){m_hSocket=sock;}  
  //SCOKET的HANDLE设定  
  voidDetach(void){m_hSocket=INVALID_  
  SOCKET;}//SCOKET的HANDLE切断  
  virtualvoidClose();//SCOKET的CLOSE  
  BOOLListen(intnConnectionBacklog=5);//连接监听  
  virtualBOOLAccept(CBlockingSocket&  
  rConnectedSocketCSockAddr*lpSockAddr=NULL);  
  //连接认可  
  BOOLConnect(CSockAddr&addr)//请求连接  
  {  
  if(connect(m_hSocket,addr,addr.GetSize())==  
  SOCKET_ERROR){  
  returnFALSE;  
  }else{  
  returnTRUE;  
  }  
  }  
  //接受数据TIMEOUT的设定  
  virtualvoidSetReceiveTimeout(intmsec)  
  {m_ReceiveTimeout=msec;}  
  virtualintReceive(void*  
  lpBuf,intnBufLen,intnFlags=0);//数据接收  
  virtualintReceive(void);//一个文字接受  
  virtualintSend(constvoid*lpBuf,intnBufLen,  
  intnFlags=0);//送信  
  //数据块送信  
  virtualintSendTo(constvoid*lpBuf,  
  intnBufLen,CSockAddr&addr,intnFlags=0)  
  {  
  returnsendto(m_hSocket,(constchar*)  
  lpBuf,nBufLen,nFlags,addr,addr.GetSize());  
  }  
  //数据块接收  
  virtualintReceiveFrom(void*lpBuf,intnBufLen,  
  CSockAddr&addr,intnFlags=0)  
  {  
  SOCKADDR*sa=addr;  
  intlen=addr.GetSize();  
  intret=recvfrom(m_hSocket,(char*)lpBuf,  
  nBufLen,nFlags,sa,&len);  
  returnret;  
  }  
  };  
   
  //endoffile  
  /***bsock.cpp:  
  **BlockSocketclass*/  
  #include“stdafx.h"  
  #include“winsock.h"  
  #include“bsock.h"  
  //SOCKADDR_IN构造体的作成  
  CSockAddr::CSockAddr(LPCSTRaddress,intport,intfamily)  
  {  
  SOCKADDR_IN&sockAddr=m_SockAddrIN;  
  memset(&sockAddr,0,sizeof(sockAddr));  
  sockAddr.sin_family=AF_INET;  
  //  
  if(address==NULL){  
  sockAddr.sin_addr.s_addr=htonl(INADDR_ANY);  
  }else{  
  //IP的数字或文字的判断  
  BOOLipaddr=IsIPAddress(address);  
  if(!ipaddr){  
  SetIPAddressByHost(address);  
  }else{  
  SetIPAddrees(address);  
  }  
  }  
  sockAddr.sin_port=htons((u_short)port);  
  }  
  //IP地址的检查//nnn.nnn.nnn.nnn  
  (n是[0-9])的形式检查  
  BOOLCSockAddr::IsIPAddress(LPCSTRaddress)  
  {  
  BOOLname=FALSE;  
  for(inti=0;address[i];i++){  
  if((!isdigit(address[i]))&&address[i]!=.'){  
  name=TRUE;  
  }  
  }  
  return(!name);  
  }  
   
  //SOCKET作成  
  BOOLCBlockingSocket::Socket(intnSocketType,  
  intnProtocolType,intnAddressFormat)  
  {  
  m_hSocket=socket(nAddressFormat,  
  nSocketType,nProtocolType);  
  if(m_hSocket!=INVALID_SOCKET)  
  returnTRUE;  
  TRACE(“Socket()Error\n");  
  returnFALSE;  
  }  
  //SOCKET关闭  
  voidCBlockingSocket::Close()  
  {if(m_hSocket!=INVALID_SOCKET){  
  closesocket(m_hSocket);  
  m_hSocket=INVALID_SOCKET;  
  }  
  }  
  //连接认可  
  BOOLCBlockingSocket::Accept(CBlockingSocket  
  &rConnectedSocket,CSockAddr*lpSockAddr)  
  {  
  SOCKEThTemp;  
  if(lpSockAddr){  
  SOCKADDR*addr=*lpSockAddr;  
  intaddrlen=lpSockAddr->GetSize();  
  hTemp=accept(m_hSocket,addr,&addrlen);  
  }else{  
  hTemp=accept(m_hSocket,NULL,NULL);  
  }  
  rConnectedSocket.Attach(INVALID_SOCKET);  
  if(hTemp==INVALID_SOCKET)  
  {  
  DWORDdwProblem=GetLastError();  
  TRACE(“GetLastError()=%d\n",dwProblem);  
  SetLastError(dwProblem);  
  }  
  rConnectedSocket.Attach(hTemp);  
  return(hTemp!=INVALID_SOCKET);  
  }  
  //连接监听  
  BOOLCBlockingSocket::Listen(intnConnectionBacklog)  
  {  
  if(listen(m_hSocket,nConnectionBacklog)==  
  SOCKET_ERROR){  
  returnFALSE;  
  }else{  
  returnTRUE;  
  }  
  }  
  //数据接收  
  intCBlockingSocket::Receive(void*  
  lpBuf,intnBufLen,intnFlags)  
  {  
  if(m_ReceiveTimeout==INFINITE){  
  returnrecv(m_hSocket,(LPSTR)  
  lpBuf,nBufLen,nFlags);  
  }else{  
  fd_setrfds;  
  structtimevaltv;  
  intretval;  
  FD_ZERO(&rfds);  
  FD_SET(m_hSocket,&rfds);  
  //  
  tv.tv_sec=m_ReceiveTimeout/1000;  
  tv.tv_usec=(m_ReceiveTimeout%1000)*1000;  
  retval=select(1,&rfds,NULL,NULL,&tv);  
  if(retval){  
  returnrecv(m_hSocket,(LPSTR)lpBuf,nBufLen,nFlags);  
  }else{  
  return0;//Timeout  
  }  
  }  
  }  
  //一个文字接受  
  intCBlockingSocket::Receive()  
  {intret=0;  
  if(m_BufferPointer>=m_BufferLength){  
  m_BufferPointer=0;  
  m_BufferLength=Receive((char*)m_  
  RecvBuffer,sizeof(m_RecvBuffer));  
  if(m_BufferLength==0)return-1;  
  }  
  returnm_RecvBuffer[m_BufferPointer++];  
  }  
  //送信  
  intCBlockingSocket::Send(constvoid  
  *lpBuf,intnBufLen,intnFlags)  
  {  
  returnsend(m_hSocket,(LPSTR)lpBuf,nBufLen,nFlags);  
  }  
  //Endiffile.  
  服务器程序SV  
  //SVDlg.h中定义  
   HANDLEm_hThread;  
   staticDWORDWINAPIThreadProc(CSVDlg*dlg);  
  //SVDlg.CPP加入  
  BOOLCSVDlg::OnInitDialog()  
  {  
  ....  
  DWORDthreadID;  
  m_hThread=CreateThread(NULL,0,  
  (LPTHREAD_START_ROUTINE)  
  CSVDlg::ThreadProc,  
  (LPVOID)this,0,&threadID);  
  returnTRUE;  
  //returnTRUEunlessyousetthefocustoacontrol  
  }  
  DWORDWINAPICSVDlg::ThreadProc(CSVDlg*dlg)  
  {  
  CBlockingSocketsocket;  
  socket.Socket(SOCK_DGRAM,IPPROTO_UDP);  
  CSockAddraddr(NULL,10000);  
  addr.Dump();  
  socket.Bind(addr);  
  while(1){  
  CSockAddrfrom;  
  charbuf[128];  
  intlen=socket.ReceiveFrom(buf,sizeof(buf),from);  
  if(len>0){  
  buf[len]=0;  
  CStringstr;  
  str.Format(“%s%s%d\n",buf,  
  from.GetIPString(),from.GetPort());  
  ::MessageBox(dlg->m_hWnd,str,“SV",MB_OK);  
  socket.SendTo(buf,len,from);  
  }else  
  break;  
  }  
  socket.Close();  
  return0;  
  }  
  客户端程序CL中加入:  
  voidCCLDlg::OnSendButton()  
  {  
  CStringip;  
  m_IPEdit.GetWindowText(ip);  
  CBlockingSocketsocket;  
  socket.Socket(SOCK_DGRAM,IPPROTO_UDP);  
  CSockAddraddr(NULL,10001);  
  socket.Bind(addr);  
  CSockAddrsendaddr(ip,10000);  
  socket.SendTo(“test",4,sendaddr);  
  charbuf[128];  
  intlen=socket.ReceiveFrom(buf,sizeof(buf),addr);  
  buf[len]=0;  
  CStringstr;  
  str.Format(“%s%s%d\n",buf,  
  addr.GetIPString(),addr.GetPort());  
  MessageBox(str,“CL",MB_OK);  
  socket.Close();  
  }  
   
  ----程序在VC++6.0下编译通过,在使用TCP/IP协议的Windows95/98对等局域网和使用TCP/IP协议的WindowsNT局域网上运行良好。  
  (完)Top

9 楼superdreamer(只懂一点点!)回复于 2006-03-07 11:00:42 得分 0

int   InitTftpServer(unsigned   short   port)  
  {  
  int   fd;  
  struct   sockaddr_in   local;  
  int   ret;  
   
  local.sin_family   =   AF_INET;  
  local.sin_port   =   htons(port);  
  local.sin_addr.s_addr   =   htonl(INADDR_ANY);  
   
  fd   =   socket(AF_INET,   SOCK_DGRAM,   0);  
  if   (fd   <   0)  
  {  
  AfxMessageBox("Init   TFTP   Server   Error");  
  return   -1;  
  }  
  ret   =   bind(fd,   (struct   sockaddr   *)&local,   sizeof(local));  
  if   (ret   <   0)  
  {  
  AfxMessageBox("TFTP   Server   Bind   Error");  
  return   -1;  
  }  
  return   fd;  
  }  
  //Process   something   from   TFTP   CLIENT  
  UINT     HandleTftp(LPVOID   lpParam)  
  {  
  struct   sockaddr_in   from;  
  int   from_len;  
  char   buffer[2048];  
  int   len;  
  int   ret;  
   
  int   fd;    
  fd   =     InitTftpServer(69);  
   
  if   (fd   <   0)  
  return   -1;  
  char   tmp[123];  
  sprintf(tmp,   "fd   =   %d\n",   fd);  
  AfxMessageBox(tmp);  
   
  while(1)  
  {  
  CString   tmpstr;  
   
  memset((void   *)buffer,   0,   sizeof(buffer));  
  len   =   recvfrom(fd,   buffer,   sizeof(buffer),   0,   (struct   sockaddr   *)&from,   &from_len);  
  //if   (len   ==   SOCKET_ERROR)  
  tmpstr.Format("recvlen   =   %d",   len);  
  //AfxMessageBox(tmpstr);  
   
   
  if   (len   <   0)  
  {  
  //AfxMessageBox("Recv   Data   Error");  
  continue;  
  }  
  ret   =   ProcessTftpData(fd,   buffer,   (struct   sockaddr   *)&from);  
  }  
  return   0;  
  }  
  void   CFactoryProgramDlg::OnStart()    
  {  
  //   TODO:   Add   your   control   notification   handler   code   here  
  AfxBeginThread(HandleTftp,(LPVOID)NULL,THREAD_PRIORITY_NORMAL,  
      0,0,NULL);  
  );  
   
  }  
  很简单的一个测试程序,   启动后用netstat   -na   都可以看到在69端口上听,但用扫描程序却发现69端口没有打开,     但就是接收不到数据Top

10 楼flowstar(研究网络中。。。)回复于 2006-03-07 13:00:02 得分 0

很可能是客户端的问题!Top

11 楼tudou614(魔蟹座的SATAN)回复于 2006-03-07 21:59:00 得分 0

mkTop

12 楼mosing(A Crimson Cosmos)回复于 2006-03-08 08:10:23 得分 0

len   =   recvfrom(fd,   buffer,   sizeof(buffer),   0,   (struct   sockaddr   *)&from,   &from_len);  
  其中的   from_len   未初始化。  
  from_len   =   sizeof(from);  
  Top

相关问题

  • 如何调试网络应用程序!
  • DOS下的网络应用开发
  • 多线程啊多线程
  • 多线程socket!!!
  • 多线程
  • 多线程
  • 多线程
  • 多线程
  • CSocket 多线程
  • java多线程

关键词

  • tcp/ip
  • vc++
  • 协议
  • 数据
  • 连接
  • 服务器
  • 通信
  • 客户机
  • 应用程序
  • 检查

得分解答快速导航

  • 帖主:superdreamer
  • DentistryDoctor
  • orbit
  • nuaawenlin
  • nuaawenlin
  • oyljerry
  • YufengShi
  • LongLongAgoImBoy

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo