TCP/IP与OSI7层参考模型的对应关系
OSI的第12层也就是物理层和数据链路层对应于TCP/IP的网络接口;
OSI的第3层网络层对应TCP/IP的网络层;
OSI的传输层对应TCP/IP的传输层;
OSI的567层也就是会话层,表示层, 应用层对应TCP/IP的应用层;
OSI参考模型并不是真正存在的7层;
OSI各层所使用的协议:
应用层:远程登录协议Telnet, 文件传输协议FTP, 超文本传输协议HTTP, 域名服务DNS, 简单右键传输协议SMTP, 邮局协议POP3等;
传输层:传输控制协议TCP, 用户数据包协议UDP;
TCP:面向连接的可靠传输协议;
UDP:无连接的不可靠的传输协议;(发送不管对方是否收到)
网络层:网络协议IP, Internet互联网控制报文协议ICMP, Internet组管理协议IGMP;
在MFC里面编写一个基于TCP的网络聊天程序步骤如下:
服务器端:
1,创建一个基本对话框;
2,向对话框中添加2个编辑框,和1个用来发送数据的按钮,一个发送编辑框, 一个接收消息编辑框, 其中接收消息的编辑框设置如下;
3,在初始化对话框中添加如下代码,用于在接收编辑框中获得并显示本机的IP地址
send_edit.SetFocus();
char name[80];
CString IP;
hostent* pHost;
gethostname(name, 128);
pHost = gethostbyname(name);//获得主机结构
IP = inet_ntoa(*(in_addr *)pHost->h_addr);
update("本机IP地址:" + IP);
AfxBeginThread(&server_thd, 0);//服务器线程开始;
return TRUE;
4.全局线程函数定义
UINT server_thd(LPVOID p)
{
WSADATA wsaData;
WORD wVersion;
wVersion = MAKEWORD(2, 2);
WSAStartup(wVersion, &wsaData);
// WSAStartup(0x0202, &wsaData);
SOCKADDR_IN local_addr;
SOCKADDR_IN client_addr;
int iaddrSize = sizeof(SOCKADDR_IN);
int res;
char msg[1024];
CsFileDlg * dlg = (CsFileDlg *)AfxGetApp()->GetMainWnd();
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(5150);
local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if ((listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
dlg->update("创建监听失败");
}
if (bind(listen_sock, (struct sockaddr*) &local_addr, sizeof(SOCKADDR_IN)))
{
dlg->update("绑定错误");
}
listen(listen_sock, 5);//最大用户数
if ((sock = accept(listen_sock, (struct sockaddr *)&client_addr, &iaddrSize)) == INVALID_SOCKET)
{
dlg->update("接收失败!");
}
else
{
CString port;
port.Format("%d", int(ntohs(client_addr.sin_port)));
dlg->update("已连接来自:" + CString(inet_ntoa(client_addr.sin_addr)) + "\n 端口:" +
port);
}
接收数据
while (1)
{
if ((res = recv(sock, msg, 1024, 0)) == -1)
{
dlg->update("失去连接");
break;
}
else
{
msg[res] = '\0';
dlg->update("client:" + CString(msg));
}
}
return 0;
4,数据刷新函数update()
void CsFileDlg::update(CString s)
{
show_edit.ReplaceSel(s + "\r\n");
}
5,发送数据
void CsFileDlg::OnBnClickedBtnsend()
{
// TODO: 在此添加控件通知处理程序代码
CString s;
char * msg;
send_edit.GetWindowText(s);
msg = s.GetBuffer(s.GetLength());
if (send(sock, msg, strlen(msg), 0) == SOCKET_ERROR)
{
show_edit.ReplaceSel("发送失败\r\n");
}
else if (s == "")
{
MessageBox("请输入信息");
}
else
{
show_edit.ReplaceSel("server:" + s + "\r\n");//消息上屏,清空输入,并重获焦点
send_edit.SetWindowText("");
send_edit.SetFocus();
}
}