多线程 网络应用, 帮忙看看, 谢谢! 要实现一个TFTP SERVER, 我建立一个DLG 项目, 加一个BUTTON , 点击后创建一个线程, 线程函数就是建立一个SOCKET 并BIND在69 端口上, 然后就在那儿recvfrom(),启动后用TFTP CLIENT对他发送或读取数据, 但SERVER返回值一直都是-1 , 根本就没收到CLIENT的请求, WHY? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 正常情况下recvfrom应该堵赛直到有client发送的sendto数据报到来,刻检查是不是这样,并检查recvfrom的返回值 使用WSAGetLastError看看错误信息是什么 用套接口实现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());}};(未完) //CBlockingSocketclassclassCBlockingSocket{protected:public:intm_BufferPointer;//1文字接受BUFFERintm_BufferLength;BYTEm_RecvBuffer[1024];intm_ReceiveTimeout;//收数据TIMEOUT//SOCKETHANDLESOCKETm_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的CLOSEBOOLListen(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);}elsebreak;}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局域网上运行良好。(完) 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 CLIENTUINT 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端口没有打开, 但就是接收不到数据 len = recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr *)&from, &from_len);其中的 from_len 未初始化。from_len = sizeof(from); MVP礼包的无比郁闷的事 VC6.0编译器问题 /*边界表示的种子填充算法*/ --如何在划分视图里加入formview的对话框 如何判断一个ip是不是国内的ip? 如何判断字符串合法,即以汉字或英文开头,中间不含./,;'等非法字符 一个错误,请大侠指点 菜鸟的弱问题! 不要笑《--- 怎么直接读取从网卡传入的数据 各位程序员,你们关心软件市场的走向吗? 我老是得不到combo box的焦點,在CBS_DROPDOWN的情況下!爲什麽呢? [诚聘]上海游猫网络科技有限公司诚聘开发人才
有限公司(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());
}
};
(未完)
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局域网上运行良好。
(完)
{
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端口没有打开, 但就是接收不到数据
其中的 from_len 未初始化。
from_len = sizeof(from);