UDP的传输功能

链接:http://blog.youkuaiyun.com/wanjingwei/archive/2009/07/02/4317036.aspx

UDP的传输功能

最近看了几个聊天室和发送文件的代码,觉得比较有意思。于是我就想自己也试着弄一个这样的程序出来,下面开始介绍我乱搞的这个程序。界面是模仿飞鸽的界面,但功能比那个菜多了,比山寨还山寨。只有传消息和传文件的功能。

首先定义两个结构体:

//这个是用户信息结构体,有主机名和IP地址。呆会要添加到列表狂里

typedef struct userInfo{
 char myhost[256];
 char ip[256];
}USERINFO,*PUSERINFO;

//这个是包含窗口句柄和套接字句柄的结构体。在向进程传递指针时用到这个

struct RECVPARAM{
 HWND hWnd;
 SOCKET sock;
};

 

  1. BOOL CMsgDlg::OnInitDialog()  
  2. {  
  3. WSADATA wsadata;  
  4.     WSAStartup(MAKEWORD(2,2),&wsadata);  
  5.   
  6.     /*下面部分是控件的初始化工作*/  
  7.   
  8.     //初始化列表控件  
  9.     m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP);  
  10.     m_list.InsertColumn(0,"IP地址",LVCFMT_LEFT,100);  
  11.     m_list.InsertColumn(1,"群组",LVCFMT_LEFT,100);  
  12.     m_list.InsertColumn(2,"主机名",LVCFMT_LEFT,100);  
  13.       
  14.     //用户登陆后执行的操作  
  15.     //获得主机名  
  16.     PUSERINFO puser=(PUSERINFO)::GlobalAlloc(GPTR,sizeof(userInfo));//申请一个指针对象  
  17.     gethostname(puser->myhost,256);  
  18.       
  19.     //获得IP地址  
  20.     hostent*phost=gethostbyname(puser->myhost);  
  21.     char *p=phost->h_addr_list[0];  
  22.     in_addr sin;  
  23.     memcpy(&sin.S_un.S_addr,p,phost->h_length);  
  24.     strcpy(puser->ip,inet_ntoa(sin));  
  25.       
  26.     AddMyInfo(puser);//先添加自己的信息  
  27.     PostAndRecvInfo(puser);//再发送给所有其他用户自己的信息  
  28.       
  29.     GlobalFree(p);//记得要释放,不然结束程序时会提示出错  
  30.       
  31.     //显示在线人数  
  32.     CString struser;  
  33.     struser.Format("在线%d人",user);  
  34.     SetDlgItemText(IDC_EDIT1,struser);  
  35. /*发送文件部分的操作,专门建立一个套接字在5000端口上收发文件*/  
  36.     m_socket=socket(AF_INET,SOCK_DGRAM,0);  
  37.     if(INVALID_SOCKET==m_socket)     
  38.     {     
  39.         MessageBox("套接字创建失败!");     
  40.         return FALSE;     
  41.     }     
  42.     SOCKADDR_IN addrSock;     
  43.     addrSock.sin_family=AF_INET;     
  44.     addrSock.sin_port=htons(5000);     
  45.     addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);     
  46.     //绑定套接字    
  47.     BOOL resue;  
  48.     setsockopt(m_socket,SOL_SOCKET,SO_REUSEADDR,(char*)&resue,sizeof(BOOL));  
  49.     int retval;     
  50.     retval=bind(m_socket, (SOCKADDR*)&addrSock,     
  51.         sizeof(SOCKADDR));     
  52.     if(SOCKET_ERROR==retval)     
  53.     {     
  54.         closesocket(m_socket);     
  55.         MessageBox("绑定失败了!");     
  56.         return FALSE;     
  57.     }     
  58.     //套接字设置成阻塞的  
  59.     u_long ul=0;  
  60.     ioctlsocket(m_socket,FIONBIO,(u_long*)&ul);  
  61.     //产生一个用于接收数据的线程      
  62.     struct RECVPARAM *pRecvParam=new RECVPARAM;     
  63.     pRecvParam->sock=m_socket;     
  64.     pRecvParam->hWnd=m_hWnd;     
  65.     HANDLE hThread=CreateThread(NULL, 0, RecvProc,     
  66.         (LPVOID)pRecvParam, 0, NULL);     
  67.     CloseHandle(hThread);     
  68.     return TRUE;  // return TRUE  unless you set the focus to a control  
  69. }  
  70.   
  71. void CMsgDlg::AddMyInfo(userInfo * p)  
  72. {  
  73.     //现在自己的界面上添加自己的信息  
  74.       
  75.       
  76.       
  77.     user = m_list.InsertItem(0, "1");//插入一行  
  78.     m_list.SetItemText(user,0,p->ip);  
  79.     m_list.SetItemText(user,2,p->myhost);//对应行的某列加数据  
  80.       
  81.       
  82.     user++;//在线人数  
  83.       
  84. }  
  85.   
  86. void CMsgDlg::PostAndRecvInfo(userInfo *p)  
  87. {  
  88.     //先发送广播给所有用户  
  89.     SOCKET broadsocket=socket(AF_INET,SOCK_DGRAM,0);  
  90.     BOOL bBroad=TRUE;  
  91.     setsockopt(broadsocket,SOL_SOCKET,SO_BROADCAST,(char*)&bBroad,sizeof(BOOL));  
  92.     //设置广播地址  
  93.     SOCKADDR_IN m_cast;  
  94.     m_cast.sin_addr.S_un.S_addr=INADDR_BROADCAST;  
  95.     m_cast.sin_family=AF_INET;  
  96.     m_cast.sin_port=htons(6000);  
  97.     //发送广播  
  98.     char *sendbuf=new char[256];  
  99.     CString use;  
  100.     int lenhost=strlen(p->myhost);  
  101.     use+=char(lenhost);//第一位为主机名长度  
  102.     use+=p->myhost;//后面几位是主机名  
  103.     int lenip=strlen(p->ip);  
  104.     use+=char(lenip);//下一位是ip地址的长度  
  105.     use+=p->ip;//最后是ip地址  
  106.     int len=use.GetLength();  
  107.     sendbuf=use.GetBuffer(len);  
  108.     sendbuf[len]='/0';  
  109.     if(sendto(broadsocket,sendbuf,strlen(sendbuf),0,(SOCKADDR*)&m_cast,sizeof(m_cast))==SOCKET_ERROR)  
  110.     {  
  111.         CString str;  
  112.         str.Format("%d",WSAGetLastError());  
  113.         MessageBox(str);  
  114.         MessageBox("发送广播数据失败!");  
  115.         return;  
  116.     }  
  117.   
  118.   
  119. //广播发送完,开始准备读取  
  120.     s=socket(AF_INET,SOCK_DGRAM,0);  
  121.       
  122.     SOCKADDR_IN m_addr;  
  123.     m_addr.sin_addr.S_un.S_addr=INADDR_ANY;  
  124.     m_addr.sin_family=AF_INET;  
  125.     m_addr.sin_port=htons(6000);  
  126.       
  127.     BOOL reuse=TRUE;  
  128.     setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&reuse,sizeof(reuse));  
  129.       
  130.     if(bind(s,(SOCKADDR*)&m_addr,sizeof(SOCKADDR))==SOCKET_ERROR)  
  131.     {  
  132.         //CString str;  
  133.         //str.Format("%d",WSAGetLastError());  
  134.         //MessageBox(str);  
  135.         MessageBox("绑定失败!");  
  136.         return ;  
  137.     }  
  138.     if(WSAAsyncSelect(s,m_hWnd,WM_SOCK,FD_READ)==SOCKET_ERROR)  
  139.     {  
  140.         MessageBox("注册网络读取事件失败!");  
  141.         return ;  
  142.     }  
  143.       
  144.   
  145.       
  146. }  
  147.   
  148. void CMsgDlg::OnSock(WPARAM wparam,LPARAM lparam)  
  149. {  
  150.       
  151.     switch(LOWORD(lparam))  
  152.     {  
  153.     case FD_READ:  
  154.         static int flag=0;  
  155.           
  156.         WSABUF wsabuf;  
  157.         wsabuf.buf=new char[200];  
  158.         wsabuf.len=200;  
  159.         DWORD dwRead;  
  160.         DWORD dwFlag=0;  
  161.         SOCKADDR_IN addrFrom;  
  162.         int len=sizeof(SOCKADDR);  
  163.           
  164.         CString strTemp;  
  165.         CString str;  
  166.       
  167.         if(SOCKET_ERROR==WSARecvFrom(s,&wsabuf,1,&dwRead,&dwFlag,  
  168.             (SOCKADDR*)&addrFrom,&len,NULL,NULL))  
  169.         {  
  170.             //MessageBox("接收数据失败!");  
  171.             return ;  
  172.         }  
  173.         //发送过来的是广播用户信息  
  174.         if(wsabuf.buf[0]>0&&wsabuf.buf[0]<65)  
  175.         {  
  176.         flag++;  
  177.         if(flag%2==0)  
  178.         {  
  179.         char *host;  
  180.         int hostlen=(int)wsabuf.buf[0];  
  181.         host=(char*)malloc(hostlen+1);  
  182.         for(int i=0;i<hostlen;i++)  
  183.         host[i]=wsabuf.buf[i+1];  
  184.         host[hostlen]='/0';  
  185.         char *ip;  
  186.         int iplen=(int)wsabuf.buf[hostlen+1];  
  187.         ip=(char*)malloc(iplen+1);  
  188.         for(i=0;i<iplen;i++)  
  189.         ip[i]=wsabuf.buf[hostlen+2+i];  
  190.         ip[iplen]='/0';  
  191.         int row=m_list.InsertItem(user,"12");  
  192.         m_list.SetItemText(row,0,ip);  
  193.         m_list.SetItemText(row,2,host);  
  194.         user++;  
  195.         //SetTimer(1,1000,NULL);  
  196.         }  
  197.         }  
  198.   
  199.         //发送来的是聊天消息  
  200.         if(wsabuf.buf[0]=='M')  
  201.         {  
  202.             CString strrecv;  
  203.             int len=(int)wsabuf.buf[1];  
  204.             char *recv=new char[len+1];  
  205.             for(int i=0;i<len;i++)  
  206.                 recv[i]=wsabuf.buf[i+2];  
  207.             recv[len]='/0';  
  208.             strrecv.Format("用户%s发来消息:%s",inet_ntoa(addrFrom.sin_addr),recv);  
  209.             SetDlgItemText(IDC_SEND,strrecv);  
  210.               
  211.         }  
  212.   
  213.   
  214.         break;  
  215.     }  
  216. }  
  217.   
  218. //定时器,每隔一段时间刷新一下在线人数  
  219. void CMsgDlg::OnTimer(UINT nIDEvent)   
  220. {  
  221.     // TODO: Add your message handler code here and/or call default  
  222.     CString struser;  
  223.     struser.Format("在线%d人",user);  
  224.     SetDlgItemText(IDC_EDIT1,struser);  
  225.     CDialog::OnTimer(nIDEvent);  
  226. }  
  227. //下面是发送消息的函数  
  228. void CMsgDlg::OnBtnsend()   
  229. {  
  230.     // TODO: Add your control notification handler code here  
  231.   
  232. //获得选中行的某一列内容(这里为第一列)  
  233. CString strsend;  
  234. int nItem = m_list.GetItemCount();  
  235. for (int i=0; i<nItem; i++)  
  236. {  
  237.     if (m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED) //  该行选中的话  
  238.     {  
  239.         sItem1 = m_list.GetItemText(i, 0);//  i为该行索引, 0表示第1列  
  240.         break;  
  241.     }  
  242. }  
  243.   
  244. GetDlgItemText(IDC_SEND,strsend);  
  245. char *sendbuf=new char[256];  
  246. sendbuf[0]='M';  
  247. int len=strsend.GetLength();  
  248. sendbuf[1]=char(len);  
  249. strcpy(&sendbuf[2],strsend.GetBuffer(len));  
  250.   
  251. SOCKADDR_IN m_addrto;  
  252. m_addrto.sin_addr.S_un.S_addr=inet_addr(sItem1);  
  253. m_addrto.sin_family=AF_INET;  
  254. m_addrto.sin_port=htons(6000);  
  255.   
  256. //套接字s在前面已经创建并绑定过了,这里直接发送就可以了  
  257. int ret=sendto(s,sendbuf,strlen(sendbuf),0,(SOCKADDR*)&m_addrto,sizeof(SOCKADDR));  
  258. if(ret==SOCKET_ERROR)  
  259. {  
  260.     MessageBox("发送数据失败!");  
  261.     return;  
  262. }  
  263. SetDlgItemText(IDC_SEND,"");  
  264. }  
  265. /*下面开始文件传输部分的操作*/  
  266.   
  267. //这个是向导里添加的一个右键的命令相应  
  268. void CMsgDlg::OnRclickList1(NMHDR* pNMHDR, LRESULT* pResult)   
  269. {  
  270.     // TODO: Add your control notification handler code here  
  271.     NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;  
  272.     //为-1时就表示右击了列表框上的某一行  
  273.     if(pNMListView->iItem != -1)  
  274.     {  
  275.         DWORD dwPos = GetMessagePos();  
  276.         CPoint point( LOWORD(dwPos), HIWORD(dwPos) );  
  277.           
  278.         CMenu menu;  
  279.         VERIFY( menu.LoadMenu( IDR_MENU1 ) );  
  280.         CMenu* popup = menu.GetSubMenu(0);  
  281.         ASSERT( popup != NULL );  
  282.         popup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this );  
  283.     }   
  284.   
  285.   
  286.     *pResult = 0;  
  287. }  
  288.   
  289. //发送文件的函数,这里发送文件和接收文件用的都是网上现成的代码,不是自己的成果  
  290. void CMsgDlg::OnSendfile()   
  291. {  
  292.     // TODO: Add your command handler code here  
  293.     CFileDialog dlg(TRUE);  
  294.     if(IDOK==dlg.DoModal())  
  295.     {  
  296.         m_filePath=dlg.GetPathName();  
  297.   
  298.         if (m_posting)  //bool isPosting 表示程序是否正在发送文件      
  299.         {     
  300.             MessageBox("数据发送中,请稍候再试。");     
  301.             return;     
  302.         }     
  303.           
  304.         WIN32_FIND_DATA FindFileData;     
  305.           
  306.         if (INVALID_HANDLE_VALUE == FindFirstFile(m_filePath, &FindFileData))     
  307.         {     
  308.             MessageBox("文件路径错误或文件不存在!/n请重新指定文件路径。");     
  309.             return;     
  310.         }   
  311.           
  312.         SOCKADDR_IN addrTo;     
  313.         addrTo.sin_family=AF_INET;     
  314.         addrTo.sin_port=htons(5000);     
  315.         addrTo.sin_addr.S_un.S_addr=inet_addr(sItem1);  
  316.   
  317.         //构建文件信息数据块      
  318.         char sendBuf[274];     
  319.         int i;    
  320.         //消息头      
  321.         sendBuf[0] = 'H';     
  322.         //文件名      
  323.         for (i = 1; i <= 256 && FindFileData.cFileName[i-1] != '/0'; i++)     
  324.             sendBuf[i] = FindFileData.cFileName[i-1];     
  325.         sendBuf[i] = '/0';     
  326.         //文件大小      
  327.         _itoa(FindFileData.nFileSizeLow, &sendBuf[257], 10);     
  328.         sendBuf[273] = '/0';   
  329.         //发送数据块      
  330.         sendto(s, sendBuf, 274, 0,     
  331.             (SOCKADDR*)&addrTo, sizeof(SOCKADDR));  
  332.         //打开文件,等待读取      
  333.         if (!(m_file = fopen(m_filePath, "rb")))     
  334.         {     
  335.             MessageBox("读取文件失败!");     
  336.         }     
  337.           
  338.         m_nSend=0;//文件块数  
  339.           
  340.         m_nFileSize_s = FindFileData.nFileSizeLow;  //文件大小  
  341.     //  m_progress.SetRange(0, m_nFileSize_s/256+1);//设置发送进度条      
  342.         m_posting = true;   //标明发送正进行   
  343.       MessageBox("发送文件成功");  
  344.     }  
  345. }  
  346.   
  347. DWORD WINAPI CMsgDlg::RecvProc(LPVOID lpParameter)     
  348. {     
  349.     SOCKET sock=((RECVPARAM*)lpParameter)->sock;     
  350.     HWND hWnd=((RECVPARAM*)lpParameter)->hWnd;   
  351.     delete lpParameter;  
  352.   
  353.     SOCKADDR_IN addrFrom;  
  354.     addrFrom.sin_port=htons(5000);  
  355.     addrFrom.sin_family=AF_INET;  
  356.     addrFrom.sin_addr.S_un.S_addr=INADDR_ANY;  
  357.     int len=sizeof(SOCKADDR);     
  358.     char recvBuf[274];        //256+17字节的接受缓冲数组      
  359.     char fileName[256];       //256字节的文件名存储区      
  360.     int retval, i;     
  361.     FILE* file = NULL;     
  362.     
  363.     while(1)  
  364.     {  
  365.         //接收UDP数据  
  366.         retval=recvfrom(sock,recvBuf,274,0,  
  367.             (SOCKADDR*)&addrFrom,&len);  
  368.         if(SOCKET_ERROR==retval)  
  369.         break;  
  370.         //收到消息头为'R',即对方同意让你继续发送数据      
  371.        if (recvBuf[0] == 'R')     
  372.         {     
  373.             char wParam = 'R';     
  374.             ::PostMessage(hWnd, WM_READY_TO_RECEIVE,     
  375.                 (WPARAM)&wParam, 0);     
  376.         }     
  377.         //收到消息头为'D',即对方拒绝让你继续发送数据      
  378.         else if (recvBuf[0] == 'D')     
  379.         {     
  380.             char wParam = 'D';     
  381.             ::PostMessage(hWnd, WM_READY_TO_RECEIVE,     
  382.                 (WPARAM)&wParam, 0);     
  383.         }    
  384.           
  385.         //收到消息头为'H',即对方申请给你发送信息,并送来文件的信息      
  386.         else if (recvBuf[0] == 'H')     
  387.         {  
  388.             //从收到的数据中提取文件名信息              
  389.             for (i = 1; i <= 256 && recvBuf[i] != '/0'; i++)     
  390.                 fileName[i-1] = recvBuf[i];   //recvBuf[1]到recvBuf[256]为文件名  
  391.             fileName[i-1] = '/0';  
  392.   
  393.             //从收到的数据中提取文件大小信息      
  394.             CString recvMsg;     
  395.             nFileSize = atoi(&recvBuf[257]); //recvBuf[257]开始是文件大小信息,把字符串变整数    
  396.             recvMsg.Format("收到来自于(%s)的文件:%s/n文件大小:%i字节/n是否接收?",     
  397.             inet_ntoa(addrFrom.sin_addr), fileName, nFileSize);  
  398.   
  399.             //用消息框提示用户有人要发送文件      
  400.             if (IDOK == AfxMessageBox(recvMsg, MB_OKCANCEL))     
  401.             {     
  402.                 //若用户同意接收,提供一个文件保存对话框用于设定保存的路径      
  403.                 CFileDialog saveDlg(false, NULL, fileName);     
  404.                 if (IDOK == saveDlg.DoModal())     
  405.                 {     
  406.                     //创建一个文件用于复制接收的文件数据      
  407.                     if (!(file = fopen(saveDlg.GetPathName(), "wb")))     
  408.                     {     
  409.                         AfxMessageBox("创建本地文件失败!");     
  410.                         continue;     
  411.                     }     
  412.                     char wParam = 'H';     
  413.                     ::PostMessage(hWnd, WM_READY_TO_RECEIVE,      
  414.                         (WPARAM)&wParam, (LPARAM)&addrFrom);                         
  415.                     
  416.                 }  
  417.                 else    
  418.                 {     
  419.                     char wParam = 'C';     
  420.                     ::PostMessage(hWnd, WM_READY_TO_RECEIVE,      
  421.                         (WPARAM)&wParam, (LPARAM)&addrFrom);     
  422.                 }     
  423.   
  424.             }  
  425.             else    //用户拒绝接收      
  426.             {     
  427.                 char wParam = 'C';     
  428.                 ::PostMessage(hWnd, WM_READY_TO_RECEIVE,      
  429.                     (WPARAM)&wParam, (LPARAM)&addrFrom);     
  430.             }     
  431.   
  432.   
  433.         }  
  434.         //收到的消息头为'F',即对方发来的是文件数据      
  435.         else if (recvBuf[0] == 'F')     
  436.         {     
  437.             //将文件数据写入本地文件中      
  438.             fwrite(&recvBuf[18], 1, 256, file); //recvBuf[18]开始是文件的数据块了    
  439.             char wParam = 'F';     
  440.             ::PostMessage(hWnd, WM_READY_TO_RECEIVE,      
  441.                 (WPARAM)&wParam, (LPARAM)&addrFrom);     
  442.         }     
  443.         //收到的消息头为'E',即对方发来最后一个数据块      
  444.         else if (recvBuf[0] == 'E')     
  445.         {     
  446.             //获取数据块的大小      
  447.             int bufSize = atoi(&recvBuf[1]);     
  448.             //将数据块写入本地文件,并关闭文件      
  449.             fwrite(&recvBuf[0x12], 1, bufSize, file);     
  450.             fclose(file);     
  451.             char wParam = 'E';     
  452.             ::PostMessage(hWnd, WM_READY_TO_RECEIVE,      
  453.                 (WPARAM)&wParam, (LPARAM)&addrFrom);     
  454.         }    
  455.         else    
  456.             AfxMessageBox("传送数据过程中出现错误!");     
  457.   
  458.   
  459.         }      
  460. return 0;  
  461. }  
  462.   
  463. void CMsgDlg::OnReadyToRecv(WPARAM wParam,LPARAM lParam)     
  464. {   
  465.     char sendBuf[0x112];     
  466.    
  467.     SOCKADDR_IN addrTo;     
  468.     addrTo.sin_family=AF_INET;     
  469.     addrTo.sin_port=htons(5000);     
  470.     addrTo.sin_addr.S_un.S_addr=inet_addr(sItem1);     
  471.       
  472.     int nRead;     
  473.         CString str;  
  474.     switch (*(char*)wParam)     
  475.     {     
  476.         //对方拒绝接收文件,关闭已打开的文件      
  477.     case 'D':   
  478.         MessageBox("对方拒绝接受你发送的文件!");     
  479.         fclose(m_file);     
  480.         m_posting = false;     
  481.         break;     
  482.           
  483.         //对方同意接收文件      
  484.     case 'R':  
  485.         nRead = fread(&sendBuf[18], 1, 256, m_file);    
  486.         //读取的文件小于256字节,则读到文件尾      
  487.         if (nRead < 0x100)     
  488.         {     
  489.             sendBuf[0] = 'E';     
  490.             _itoa(nRead, &sendBuf[1], 10);     
  491.             sendto(m_socket, sendBuf, nRead+0x12, 0,     
  492.                 (SOCKADDR*)&addrTo, sizeof(SOCKADDR));     
  493.             fclose(m_file);     
  494.                
  495.             m_posting = false;          
  496.             MessageBox("发送完毕!");     
  497.                  
  498.         }     
  499.         //读到文件等于256字节,则文件还未读完      
  500.         else    
  501.         {     
  502.             sendBuf[0] = 'F';     
  503.             sendto(m_socket, sendBuf, 0x112, 0,     
  504.                 (SOCKADDR*)&addrTo, sizeof(SOCKADDR));     
  505.             
  506.             m_nSend++;     
  507.               
  508.             m_send.Format("发送进度:(%.1f%%)",     
  509.                 (float)m_nSend/(m_nFileSize_s/0x100+1)*100);  
  510.                 
  511.         }     
  512.         break;     
  513.         //同意接收对方文件  
  514.     case 'H':     
  515.        MessageBox("同意接收了");  
  516.         m_nRecv = 0;   
  517.     case 'F':     
  518.         sendto(m_socket, "R", 2, 0,     
  519.             (SOCKADDR*)&addrTo, sizeof(SOCKADDR));     
  520.            
  521.         m_nRecv++;     
  522.       
  523.         //str.Format("%d",m_nRecv);  
  524.         //MessageBox(str);  
  525.         m_recv.Format("接收进度:(%.1f%%)", (float)m_nRecv/(nFileSize/0x100+1)*100);   
  526.            
  527.         break;   
  528.         //接受完毕,提示用户      
  529.     case 'E':       
  530.         MessageBox("接收完毕!");     
  531.     
  532.         break;  
  533.         //拒绝接收,通知对方      
  534.     case 'C':     
  535.         sendto(m_socket, "D", 2, 0,     
  536.             (SOCKADDR*)&addrTo, sizeof(SOCKADDR));     
  537.         break;     
  538.     }     
  539. }  

 

代码很麻烦也很乱,但基本功能是实现了。还剩下用户正常退出或异常退出时处理没有写,这个目前还没想到该怎么弄才好,先留着以后学了别的知识或许就能轻易解决了。

不怕自己笨,就怕自己不努力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值