1.关于tcp:
tcp是面向连接的,可靠性高。
2.通信前的注意工作:
因为采用基于windows套接口的编程,通信前,要进行初始化Windows Sockets服务。
⑴用WSAStartup()函数对windowsSocketsDLL进行初始化。
⑵在调用Windock函数之前,需要加载Wincock库
#include "winsock.h"
#include "afxsock.h"
⑶WSAStartup()与WSACleanup()是成对出现的,前者是分配资源,后者则是释放资源。
3.采用C/S模型,先分析服务器程序
if(m_hSocket!=NULL)
{
closesocket(m_hSocket);//如果已经建立套接字,先关闭
m_hSocket=NULL;
}
if(m_hSocket==NULL)
{
m_hSocket=socket(AF_INET,SOCK_STREAM,0);//创建流套接字
ASSERT(m_hSocket!=NULL);
}
UpdateData();
//SOCKADDR_IN结构体的初始化:
m_addr.sin_family=AF_INET;//AF_INET表示套接字处于internet域
m_addr.sin_addr.S_un.S_addr=INADDR_ANY;//IP地址设为INADDR_ANY,监听所有网络接口
m_addr.sin_port=htons(m_port);//主机字节顺序转成网络字节顺序
int ret=0;
int error=0;
ret=bind(m_hSocket,(LPSOCKADDR)&m_addr,sizeof(m_addr));//绑定套接字到本机地址
if(ret==SOCKET_ERROR)
{
TRACE("bind error:%d/n",(error=WSAGetLastError()));
return;
}
ret=listen(m_hSocket,1);//帧听
if(ret==SOCKET_ERROR)
{
TRACE("listen error:%d/n",(error=WSAGetLastError()));
return;
}
SOCKET s=accept(m_hSocket,NULL,NULL);//接受用户连接请求
if(s==SOCKET_ERROR)
{
TRACE("accept error:%d/n",(error=WSAGetLastError()));
return;
}
char buff[256];
ret=recv(s,buff,256,0);//数据接收函数
buff[ret]=0;
if(ret==0||ret==SOCKET_ERROR)
{
TRACE("recv data error:%d/n",WSAGetLastError());
return;
}
MessageBox(buff);
char* name=NULL;
char* password=NULL;
int len=0;
len=buff[0];
name=new char[len+1];
for(int i=0;i<len;i++)
name[i]=buff[i+1];
int len2=buff[len+1];
password=new char[len2+1];
for(int i=0;i<len2;i++)
password[i]=buff[i+2+len];
password[len2]='/0';
name[len]='/0';
CString str;
if(strcmp(name,"wuzhoujing")!=0)
{
str="用户名不对!";
}
else
{
if(strcmp(password,"xiaowu")!=0)
{
str="密码不对!";
}
}
if(str.IsEmpty())
{
str="帐号存在!";
}
char *buf=str.GetBuffer(0);
ret=send(s,buf,str.GetLength(),0);//数据发送函数
if(ret!=str.GetLength())
{
TRACE("send data error!%d/n",WSAGetLastError());
return;
}
delete [] name;
delete [] password;
closesocket(m_hSocket);//关闭套接字
closesocket(s);
4.客户端程序如下:
if(m_hSocket!=NULL)
{
closesocket(m_hSocket);//如果已经建立套接字,先关闭
m_hSocket=NULL;
}
if(m_hSocket==NULL)
{
m_hSocket=socket(AF_INET,SOCK_STREAM,0);//创建流套接字
ASSERT(m_hSocket!=NULL);
}
UpdateData();
//SOCKADDR_IN结构体的初始化:
m_addr.sin_family=AF_INET;//AF_INET表示套接字处于internet域
m_addr.sin_addr.S_un.S_addr=inet_addr(m_serverip.GetBuffer(0));//inet_addr函数作用:将点式IP地址转换成32位无符号长整数
m_addr.sin_port=htons(m_port);//主机字节顺序转成网络字节顺序
int ret=0;
int error=0;
ret=connect(m_hSocket,(LPSOCKADDR)&m_addr,sizeof(m_addr));//客户机请求连接服务器
if(ret==SOCKET_ERROR)//连接失败则
{
TRACE("connect error:%d/n",(error=WSAGetLastError()));
if(error==10061)
AfxMessageBox("请确认服务器确实已经打开并工作在同样的端口!");
return;
}
CString str;
str += char(m_name.GetLength());
str += m_name;
str += char(m_pass.GetLength());
str += m_pass;
char* buf = str.GetBuffer(0);
ret = send(m_hSocket, buf, str.GetLength(), 0);//数据发送函数,因为是tcp,不需要传地址参数
if(ret != str.GetLength())
{
TRACE("Send data error: %d/n", WSAGetLastError());
return ;
}
char buff[256];
ret = recv(m_hSocket, buff, 256, 0);//数据接受函数
buff[ret] = '/0';
if(ret == 0){
TRACE("Recv data error: %d/n", WSAGetLastError());
return ;
}
AfxMessageBox(buff);
closesocket(m_hSocket);//关闭套接字
5.总结:
TCP与UDP协议的不同,可以见http://blog.csdn.net/wuzoujing/archive/2007/04/06/1554024.aspx