一、服务器程序
1、创建一个名为“server” 的项目, 单文档界面。
2、在serverview.h 中加入代码:
#include “winsock.h”
添加变量:
CSize sizeTotal;// 控制滚动条
int count;// 信息条数
CString m_data[1000];// 信息存放
char Hostname[260];
char Hostaddress[20];// 主机IP 地址
SOCKET m_sock;
HANDLE m_hListenThread;// 线程
BOOL m_bInitialized;// 是否初始化
WSADATA WSAData;
BOOL flag;
SOCKADDR_IN saClnt;
int saClntLen;
BOOL Isconnect;// 是否连接
3、在serverview.cpp 中重载CServerView() 构造器, 创建并绑定嵌套字:
CServerView::CServerView()
{ // TODO: add construction code here
Isconnect=FALSE;
flag=FALSE;
sizeTotal.cy=350;
sizeTotal.cx=300;
m_hListenThread;
count=5;
int status;
WSADATA wsaData;
m_data[0]=”initializing Windows Sockets DLL….”;
if((status=WSAStartup(0×0101, &wsaData))==0)
{ m_data[0] +=”Succeeded”;
m_bInitialized=TRUE;
}
else
{ m_bInitialized=FALSE;
}
m_sock=socket(AF_INET,SOCK_DGRAM,0);
m_data[1]=”Creating socket….”;
if(m_sock==INVALID_SOCKET)
{ m_data[1] +=”Failed”;
}
m_data[1] +=”Succeeded”;
m_data[2]=”Binding socket….”;
sockaddr_in sa;
sa.sin_family=AF_INET;
sa.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
sa.sin_port=htons(5050);
if(bind(m_sock,(PSOCKADDR)
&sa,sizeof(sa))==SOCKET_ERROR)
{ m_data[2] +=”Failed”;
closesocket(m_sock);
}
m_data[2] +=”Succeeded”;
m_data[3]=”Creating listener thread….”;
unsigned long idThread;
m_hListenThread=CreateThread(NULL,0,
(LPTHREAD_START_ROUTINE)Listen,
(void if(m_hListenThread)
{ m_data[3] +=”Succeeded”;
m_data[4] +=”Listening….”;
}
else
m_data[4] +=”Failed”;
}
4、在析构函数中完成必需的清除操作:
CServerView:: ~CServerView()
{ if(m_bInitialized)
WSACleanup();
closesocket(m_sock);
if(m_hListenThread)
::TerminateThread(m_hListenThread,0);
}
5、定义接收和处理消息的线程:
long WINAPI Listen(CServerView *pView)
{ char msg[2000]=”";
int nchar;
SOCKADDR_IN saClnt;
int saClntLen;
while(1)
{ saClntLen=sizeof(saClnt);
nchar=recvfrom(pView ->m_sock,msg,1024,0,
(PSOCKADDR) &saClnt, &saClntLen);
if(nchar<0)
{ pView ->m_data[pView ->count ++] +
=”Error in recvfrom\n”;
pView ->InvalidateRect(NULL);
}
else
{switch(msg[0])
{
case ‘A’:
wsprintf(msg,”A:Client from %s attached\n”,
inet_ntoa(saClnt.sin_addr));
pView ->m_data[pView ->count ++]=msg;
pView ->flag=TRUE;
pView ->InvalidateRect(NULL);
pView ->Isconnect=TRUE;
pView ->saClnt=saClnt;
pView ->saClntLen=saClntLen;
sendto(pView ->m_sock,msg,1024,0,(PSOCKADDR)
&saClnt,saClntLen);
break;
case ‘D’:
wsprintf(msg,”D: Client form %s detached\n”,
inet_ntoa(saClnt.sin_addr));
pView ->m_data[pView ->count ++]=msg;
pView ->flag=TRUE;
pView ->InvalidateRect(NULL);
pView ->Isconnect=FALSE;
sendto(pView ->m_sock,msg,1024,0,(PSOCKADDR)
&saClnt,saClntLen);
break;
case ‘R’:
saClntLen=sizeof(saClnt);
pView ->m_data[pView ->count ++]=msg;
pView ->flag=TRUE;
pView ->InvalidateRect(NULL);
break;
default:
break;
}
}
}
return(0);
}
6、在程序菜单项中添加“本机IP 地址”:
void CServerView::OnIp()
{int WSAReturn;
WSAReturn=WSAStartup( 0×0101, &WSAData );
if( WSAReturn == 0 ){
gethostname( Hostname, 260 );
struct hostent *pHostEnt;
pHostEnt = gethostbyname( Hostname);
if( pHostEnt != NULL ){
wsprintf( Hostaddress, “%d. %d. %d. %d”,
( pHostEnt ->h_addr_list[0][0] &0x00ff ),
( pHostEnt ->h_addr_list[0][1] &0x00ff ),
( pHostEnt ->h_addr_list[0][2] &0x00ff ),
( pHostEnt ->h_addr_list[0][3] &0x00ff ) );
CString out;
out.Format(Hostaddress);
AfxMessageBox(out);
}
}
}
7、在程序菜单中添加“发送消息”:
void CServerView::OnSendmessage()
{// TODO: Add your command handler code here
char msg[2000];
Csend Sendmessage;
if(Sendmessage.DoModal()==IDOK
&&!Sendmessage.m_Message.IsEmpty())
{ wsprintf(msg,”R: ” +Sendmessage.m_Message);
sendto(m_sock,msg,1024,0,(PSOCKADDR)
&saClnt,saClntLen);
m_data[count ++]=Sendmessage.m_Message;
flag=TRUE;
InvalidateRect(NULL);
}
}
8、为发送消息项添加一个对话框的类, 名为send, 有一个文本框, 用来发送消息,并为文本框添加CString m_Message 变量, 在ServerView.cpp 中添加#include “send.h”
9、为发送消息项添加一个判断函数:
void CServerView::OnUpdateSendmessage(CCmdUI *
pCmdUI)
{// TODO: Add your command update UI handler code here
pCmdUI ->Enable(FALSE);
if(Isconnect)
pCmdUI ->Enable(TRUE);
}
10、再窗口显示消息:
void CServerView::OnDraw(CDC *pDC)
{ if(flag)
{sizeTotal.cy +=20;
for(int j=65;jTextOut(10,y,m_data);
y +=20;}
// TODO: add draw code for native data here
}
11、在Project 中点击Settings 中选择Link 项添加wsock32.lib。
最后编译程序, 就可以得到Server.exe 程序。
二、客户机程序
1、创建一个名为“client” 的项目, 单文档界面。
2、在clientview.h 中加入代码:
#include “winsock.h”
添加变量:
CString m_data[1000];
HANDLE m_hListenThread;
SOCKET m_sock;
SOCKADDR_IN m_saSrvr;
BOOL Isconnect;
int count;
CSize sizeTotal;
BOOL flag;
3、在构造函数中初始化变量:
CClientView::CClientView()
{ // TODO: add construction code here
Isconnect=FALSE;
sizeTotal.cy=350;
sizeTotal.cx=300;
flag=FALSE;
}
4、在析构函数中完成清除操作,代码如上。
5、在菜单中添加“拨号” 项:
void CClientView::OnDial()
{// TODO: Add your command handler code here
count=5;
if(m_bInitialized)
{ AfxMessageBox(“Already dialing”);
return;}
Cdial dial;
if(dial.DoModal()==IDOK
&&!dial.m_HostAddress.IsEmpty())
{m_saSrvr.sin_family=AF_INET;
m_saSrvr.sin_addr.S_un.S_addr=htonl
(INADDR_ANY);
m_saSrvr.sin_addr.S_un.S_addr=inet_addr
(dial.m_HostAddress);
m_saSrvr.sin_port=htons(5050);
int status;
WSADATA wsaData;
m_data[0]=”initializing Windows Sockets DLL….”;
if((status=WSAStartup(0×0101, &wsaData))==0)
{ m_data[0] +=”Succeeded”;
m_bInitialized=TRUE;}
else
{ m_bInitialized=FALSE;}
m_sock=socket(AF_INET,SOCK_DGRAM,0);
m_data[1]=”Creating socket….”;
if(m_sock==INVALID_SOCKET)
{ m_data[1] +=”Failed”;}
m_data[1] +=”Succeeded”;
m_data[2]=”Binding socket….”;
sockaddr_in sa;
sa.sin_family=AF_INET;
sa.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
sa.sin_port=htons(0);
if(bind(m_sock,(PSOCKADDR)
&sa,sizeof(sa))==SOCKET_ERROR)
{ m_data[2] +=”Failed”;
closesocket(m_sock);}
m_data[2] +=”Succeeded”;
m_data[3]=”Creating listener thread….”;
unsigned long idThread;
m_hListenThread=CreateThread(NULL 0,
(LPTHREAD_START_ROUTINE)Listen,
(void *)this,0, &idThread);
if(m_hListenThread)
{ m_data[3] +=”Succeeded”;
m_data[4] +=”Waiting….”;}
else
m_data[4] +=”Failed”;
InvalidateRect(NULL);
}
}
6、添加一个拨号对话框, 名为dial, 有一个文本框用来写IP 地址. 并在clientview.cpp 中添加代码:
#include dial.h
7、在拨号项添加一个判断函数:
void CClientView::OnUpdateDial(CCmdUI *
pCmdUI)
{// TODO: Add your command update UI handler code here
pCmdUI ->Enable(TRUE);
if(Isconnect)
pCmdUI ->Enable(FALSE);
}
8、添加接收与发送消息的线程:
long WINAPI Listen(CClientView *pView)
{ char msg[2000];
pView ->m_data[5]=”Sending ATTACH command”;
pView ->InvalidateRect(NULL);
wsprintf(msg,”A: “);
sendto(pView ->m_sock,msg,1024,0,(PSOCKADDR)
&pView ->m_saSrvr,sizeof(pView ->m_saSrvr));
int saSrvrLen ,nchar;
while(1)
{saSrvrLen=sizeof(pView ->m_saSrvr);
nchar=recvfrom(pView ->m_sock,msg,1024,0,
(PSOCKADDR) &pView ->m_saSrvr, &saSrvrLen);
if(nchar<0)
{ pView ->m_data[pView ->count ++]=
“Error in recvform”;
pView ->InvalidateRect(NULL);}
else
{ pView ->m_data[pView ->count ++]=msg;
pView ->Isconnect=TRUE;
pView ->flag=TRUE;
pView ->InvalidateRect(NULL);
}
}
return(0);
}
9、同主程序一样做一个发送消息项, 代码如上。
10、显示程序也与主程序一样, 代码如上。
11、在Project 中点击Settings 中选择Link 项添加wsock32.lib。
12、编译程序便可得到client.exe 程序。
server.exe 和client.exe 做完后, 就可以在具有TCP/IP 协议下的网络中执行。
>> 本文固定链接: http://www.vcgood.com/archives/499