VC++ 网络编程总结(一)
1、套接字编程原理
一个完整的网间通信进程需要由两个进程组成,并且只能用同一种高层协议。也就是说,不可能通信的一段用TCP,而另一端用UDP。一个完整的网络信息需要一个五元组来标识:协议、本地地址、本地端口号、远端地址、远端端口号。
1.1Client/Server通信模型
在客户端/服务器模式中我们将请求服务的一方成为客户,将提供某种服务的一方称为服务器(Server)
一个服务程序通常在一个众所周知的地址监听对服务的请求,也就是说服务进程一直处于休眠状态,直到一个客户对这个服务的地址提出了连接请求。在这个时刻,服务程序被“惊醒”,并且为客户提供服务----对客户的请求做出适当的反应。虽然基于链接的服务是设计客户机/服务器应用程序时的标准,但有些服务也是可以通过无连接的接口提供的。
客户及/服务器的请求/响应过程示意图如下所示:

1.2Windows Sockets规范
Windows Sockets规范从90年代的1.0版本开始,经过不断的完善和发展,目前已经有了Windows Sockets 2版本。值得注意的是,Microsoft的MFC库现在只支持Windows Sockets1版本,不支持WindowsSockets2版本。
MFC提供了两个类用以封装Windows Sockets API。一个是CAsyncSocket类,它主要是提供给那些具有一定网络编程经验,希望同时拥有Socket API编程的灵活性和类库编程便利性的开发者。另一个是CSocket类,它有CAsyncSocket类派生,它具有更高的抽象化,致力于简化网络编程所需的操作。
1.3套接字
1.3.1套接字定义
套接字是一个通信终结点,它是Sockets应用程序用来在网络上发送或接收数据包的对象。套接字具有类型,与正在运行的进程相关联,并且可以有名称。目前,套接字一般只与使用网际协议组的同一“通信域”中德其他套接字交换数据。使用套接字的应用程序间通信模型如图:

1.3.2分类
1.3.2.1流式套接字
流式套接字提供没有记录边界的数据流,即字节流。字节流能确保以正确的顺序无重复地被送达。

1.3.2.2数据报套接字
数据报套接字支持面向记录的数据流,但不能确保能被送达,也无法确保按照发送顺序或不重复。

“有序”指数据包按发送的顺序送达。“不重复”指一个特定的数据包只能获取一次。这两种套接字都是双向,是可以同时在两个方向上(全双工)进行通信的数据流.
注意:在某些网络协议下(如XNS),流可以面向记录,即作为记录流而非字节流。但在更常用的TCP/IP协议下,流为字节流,Win Sockets提供与基础协议无关的抽象化级别。
1.3.3套接字的作用
套接字的作用非常大,至少在下面三种通信上下文中如此:
- 客户端/服务器模型
- 对等网络方案,如聊天应用程序
- 通过让接受应用程序将消息解释为函数调用来进行远程过程调用
1.3.4 端口与地址
在网络上,一个套接字的标识主要借助于地址和端口来描述。
套接字的地址指该套接字所在计算机的网络地址,可以为域名或IP地址的形式。通常创建套接字时不必指明网络地址,只有在拥有多个网络地址的机器时,才需要显式指定的一个网络地址。
同一机器上可以运行多个网络应用程序,每个应用程序都有自己的套接字用以进行网络通信,此时如果只有地址表示套接字,则当一个通信包到达机器时,将无法确定究竟是哪个应用程序的套接字需要接收此信息。由此增加了端口的概念,以协助区分同一机器上不同应用程序的套接字。
段开口用于标识进程,同一机器上不同的网络应用程序各有不同的端口,这样,通过“网络地址+端口号”的标识方法,便唯一标识了机器上的应用程序了。
实例应用程序:
======客户端
#include < WINSOCK2.H>
#pragma comment( lib, "WS2_32" )
#include < stdio.h> int main()
{
printf( "------------------------\n| 客户端 |\n|---------------------------------------\n" );
//------①加载动态链接库winsock DLL-----------
printf( "|加载等待中.... " );
WSADATA wsaData;
WORD wVersionRequested= MAKEWORD( 2 ,2 );
if ( WSAStartup( wVersionRequested,& wsaData)!= 0 )
{
printf( "|WSAStartup Failed\n" );
printf( "|WSAStartup Error=%d\n" , WSAGetLastError());
}
else
{
printf( "加载Winsock 库成功 |\n" );
}
printf( "|---------------------------------------\n" );
//-------②创建用于监听的流式套接口s,使用socket()-----------------
SOCKET s= socket( AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( s== INVALID_SOCKET)
{
printf( "|Failed socket\n" );
printf( "|socket Error=%d\n" , WSAGetLastError());
}
else
printf( "|已创建用于监听的套接口,套接口号:[%u]\n" , s);
printf( "|---------------------------------------\n" );
//------③本地地址bind(可以不做这部分,如果不绑定,系统将自动分配)--------
/*struct sockaddr_in Cadd;
Cadd.sin_family=AF_INET;
Cadd.sin_port=htons(4444);
Cadd.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
if (bind(s,(sockaddr*)&Cadd,sizeof(Cadd))==SOCKET_ERROR)
{
printf("|Failed bind()/n");
}*/
//-------填写要连接的服务器地址信息---------
struct sockaddr_in Sadd;
Sadd.sin_family= AF_INET;
Sadd.sin_port= htons( 5555 );
Sadd.sin_addr.S_un.S_addr= inet_addr( "127.0.0.1" );
//--------④将套接口s与远程主机相连--------------
if ( connect( s,( sockaddr*)& Sadd, sizeof ( Sadd))== INVALID_SOCKET)
{
printf( "|Failed connect()\n" );
printf( "|connect Error=%d\n" , WSAGetLastError());
}
else
{
//####################开始发接数据########################
printf( "|连接成功,可以开始发送接收数据了!\n" );
printf( "|服务器IP地址:[%s]\n 端口号:[%u]\n" , inet_ntoa( Sadd.sin_addr), ntohs( Sadd.sin_port));
//####################结束发接数据########################
}
//--------------⑤关闭套接字s,终止对动态链接库的访问----------
closesocket( s);
printf( "|---------------------------------------\n" );
printf( "|连接完毕\n" );
WSACleanup();
return 0 ;
}
========服务端
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32") int main(int argc, char* argv[])
{
printf("---------\n| 服务端 |\n-----------");
//----------1、加载动态链接库Winsock Dll---------
WORD wVersionRequested = MAKEWORD(2,2);
WSADATA wsaData;
if(WSAStartup(wVersionRequested,&wsaData) != 0)
{
printf("WSAStartup Failed \n");
printf("WSAStartup Error = %d \n",WSAGetLastError());
}
else
{
printf("加载WinSocket成功 \n");
printf("调用者希望使用的WinSocket版本号=%x\n",wsaData.wVersion);
printf("加载的WinSock库支持最高WinSock版本号=%x \n",wsaData.wHighVersion);
printf("wWinSock库的说明字符串=%s \n",&wsaData.szDescription[0]);
printf("系统状态或配置信息的说明字符串=%s\n",&wsaData.szSystemStatus[0]);
}
//----------2、创建监听的流式套接口---------- SOCKET s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(s == INVALID_SOCKET)
{
printf("| Failed socket\n");
printf("| Socket Error = %d\n",WSAGetLastError());
}
else
printf("毅创建用于监听的套接口,套接口号:[%u]\n",s); //----3、绑定使用bind()
struct sockaddr_in Sadd;
Sadd.sin_family = AF_INET;
Sadd.sin_port = htons(5555);
Sadd.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if(bind(s,(sockaddr*)&Sadd,sizeof(Sadd)) == SOCKET_ERROR)
{
printf("Failed bind()\n");
printf("Bind Error = %d\n",WSAGetLastError());
}
else
{
printf("绑定成功\n");
printf("本地Ip地址:[%s],本地端口号:[%u]\n",inet_ntoa(Sadd.sin_addr),ntohs(Sadd.sin_port));
}
//---------------④监听状态-------------
if ( listen( s, 2 )== SOCKET_ERROR)
{
printf( "Failed listen()\n" );
printf( "listen Error=%d\n" , WSAGetLastError());
}
//----------------⑤循环接受客户的连接请求---------------------------
struct sockaddr_in Cadd;
int caddLen= sizeof ( Cadd);
SOCKET c;
while ( TRUE )
{
printf( "|----------------------------\n" );
printf( "|进入监听状态.....\n|--------------------------------|\n" );
c= accept( s,( sockaddr*)& Cadd,& caddLen);
if ( c== INVALID_SOCKET)
{
printf( "|Failed accept()\n" );
printf( "|accept Error=%d\n" , WSAGetLastError());
}
else
printf( "|可以在套接口[%u]上发送接收数据了!\n" , c);
//#########################开始发送、接收###################### 注意都要在新套接口c上进行
//#########################结束发送、接收######################
closesocket( c);
printf( "|与主机IP地址是:[%s]\n|端口号是:[%u]的连接完毕\n" , inet_ntoa( Cadd.sin_addr), ntohs( Cadd.sin_port));
char xx;
printf( "|-------------------------------------\n需要退出吗?(Y\n)" );
scanf( "%c" ,& xx);
if ( xx== 'Y' || xx== 'y' )
{
break ;
}
}
closesocket( s);
WSACleanup();
return 0;
}
运行结果:


VC++ 网络编程总结(一)的更多相关文章
- vc 网络编程(socket)
在网上找了很多的资料,现将这些资料整合起来,详细介绍一下VC下的socket编程,并提供一个服务器客户端具体的实例.希望对您有所帮助 一.原理部分 (个人觉得这篇写的可以,所以转与此,原文地址:htt ...
- VC++ 网络编程总结(二)
2.基本的Windows Socket API编程 需要在程序中添加下面的包含语句:#include <winsock2.h> #pragma comment( lib, " ...
- MFC 网络编程 -- 总结
原文链接:http://www.cnblogs.com/lidabo/archive/2012/07/19/2598734.html 1.基于 TCP 的 socket 编程 /* 服务器端程序流程: ...
- VC++学习之网络编程中的套接字
VC++学习之网络编程中的套接字 套接字,简单的说就是通信双方的一种约定,用套接字中的相关函数来完成通信过程.应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问 ...
- VC++网络高级编程
内含<VC网络高级编程>电子书 及源代码. 第一章.TCP/IP协议.第二章.Winsock网络编程接口:第二章.Visual C++与网络编程:第四章.基本网络编程技术:第五章.Teln ...
- Windows平台VC++ 6.0 下的网络编程学习 - 简单的测试winsock.h头文件
最近学习数据结构和算法学得有点累了(貌似也没那么累...)...找了本网络编程翻了翻当做打一个小基础吧,打算一边继续学习数据结构一边也看看网络编程相关的... 简单的第一次尝试,就大致梳理一下看书+自 ...
- windows网络编程的一些理论
参考自<VC++深入详解> 这是我在看书时记录下来的东西. 注:下面的Socket其实都应该是socket 第14章网络编程 Socket是连接应用程序与网络驱动程序的桥梁,Socket在 ...
- windows socket网络编程基础知识
下面介绍网络7层协议在WINDOWS的实现: 7层协议 WIN系统 ________________________________________ 7 应用层 7 应用程序 ____________ ...
- 完毕port(CompletionPort)具体解释 - 手把手教你玩转网络编程系列之三
手把手叫你玩转网络编程系列之三 完毕port(Completion Port)具体解释 ...
随机推荐
- 使用AngularJS 进行Hybrid App 开发已经有一年多时间了,这里做一个总结
一.AngularJS 初始化加载流程 1.浏览器载入HTML,然后把它解析成DOM.2.浏览器载入angular.js脚本.3.AngularJS等到DOMContentLoaded事件触发.4.A ...
- POJ 2159 Ancient Cipher
题意:被题意杀了……orz……那个替换根本就不是ASCII码加几……就是随机的换成另一个字符…… 解法:只要统计每个字母的出现次数,然后把数组排序看相不相同就行了…… 代码: #include< ...
- DevExpress 中根据数据库字典动态生成卡式菜单 z
第三方的Devexpress套件因为要使用权限机制控制不同用户进入系统显示菜单所以要配合字典数据动态生成.在WEB中这种问题灰常的轻松在winform里就稍微有点不同为了用DEV实现卡式菜单有组的概念 ...
- IOS 通知 alarm 记录
所有的内容融为一体,去除某一个项不知道结果如何. 最主要的前提:APP 会长期保留在后台 1.在info.plist 文件里面,加入 audio 后台请求 2.当APP 点击home进入后台之后,请求 ...
- cocos2d CCLayer 触摸相关
要让一个 CCLayer 能够接受触摸输入 需要进行如下设置: [selfsetTouchEnabled:YES]; cocos2d-x提供了两种触摸事件处理机制, 分别是CCStandardTo ...
- Python之正则
从学习Python至今,发现很多时候是将Python作为一种工具.特别在文本处理方面,使用起来更是游刃有余. 说到文本处理,那么正则表达式必然是一个绝好的工具,它能将一些繁杂的字符搜索或者替换以非常简 ...
- 下破解安装Python开发工具WingIDE4.1
步骤: 1.将系统时间调整到一个月之前,然后执行安装. 可以使用date命令调整系统时间,如:date -s '2012-08-14 10:00:00' 2.安装成功后,打开程序,按照提示信息,申请一 ...
- 关于C++ vector的拷贝
定义了vector变量,在使用时直接用了等号赋值,后来发现有问题,就查了一下vector怎么赋值? 说明:vector是一个构造对象,不能直接使用=符号进行复制,必须迭代每个元素来复制.或者重载=操作 ...
- lsof,nc
安装nc, yum -y install nc; 用nc传输同步文件 A,被同步端-即需要备份复制端; tar -czvf - /|nc 192.168.1.204(同步机ip,复制文件位置机) 88 ...
- Hibernate之Session缓存以及操作Session缓存的相关方法
1.Session概述 A.Session 接口是 Hibernate 向应用程序提供的操纵数据库的最主要的接口, 它提供了基本的保存, 更新, 删除和加载 Java 对象的方法. B. Sessio ...