网络编程之Socket编程基础

        最近在参加“中兴捧月”软件设计比赛,要用到一些Socket(套接字,具体含义不再赘述)编程方面的东西,之前对这个主题基本没有涉猎过,于是在看《TCP/IP详解》的基础上找了本讲解Windows 网络编程的书来看,迅速补充一下。

        在说Socket编程之前先说说三类网络编程:基于TCP/IP协议栈的网络编程、基于WWW应用的网络编程和基于.NET框架的Web Services网络编程,我们这里讨论的都是基于第一种模式,这是最基本的网络编程方式,利用操作系统提供的Socket网络编程接口,直接利用了网络协议栈提供的服务来实现网络编程所以层次比较低,并且自由度很大。这种方式要求我们首先了解TCP/IP的相关知识(关于TCP/IP此处略去一万字,太复杂,不是我等菜鸟可以说清的)和Socket网络编程接口以及深入了解网络应用层协议。

        话说Socket编程接口起源于UNIX操作系统(对此有兴趣的同学可以去百度一下),这种编程接口由于良好的设计而被Windows和Linux继承和发展,我所接触到的仅仅是Socket在Windows NT架构下的C语言接口。

        由于基于的底层协议不同Socket开发接口可以提供面向连接和无连接的两种服务,顾名思义,面向连接的就像TCP协议那样可以提供可靠服务,而无连接则像UDP一样不能保证可靠的服务。相应的Socket分为3种类型:流式套接字(SOCK_STREAM)、数据报式套接字(SOCK_DGRAM)和原始套接字(SOCK_RAW),不太懂SOCK_RAW是什么概念,百度上说原始套接字编程可以接收到本机网卡上的数据帧或者数据包,对与监听网络的流量和分析是很有作用的,使用它可以再IP层上对Socket进行编程,发送和接收IP层上的原始数据包,暂且这样理解吧。

        在Windows下我们使用WinSock是一个好的选择,最初是基于Unix环境下的BSD Socket,是一个与网络协议无关的编程接口。WinSock有两个主要的版本:WinSock1和WinSock2,相应的头文件为winsock.h和winsock2.h,需引用的库文件分别为wsock32.lib和ws2_32.lib。WinSock1.1提供的是与Unix/Linux类操作系统保持兼容的通用的、基本的函数库 ;Winsock2.2引入了与Windows内核密切相关的重叠IO机制,提供了WSA打头的,支持重叠IO的异步函数库,还将一些常用socket操作序列进行了打包封装,提供了以Ex结尾的部分函数。

        要使用Socket首先要注意的就是IP地址的表示形式,我们平时见到的IP地址形式都属于点分法表示的,而在计算机中它只是一个无符号的整数,而这就引来了一个问题,在PC中,一个字的高位存储在高地址处,叫做小端(little end)格式,而在网络传输时先传送一个字的低位,这样的格式叫做大端(big end)格式,所以说,要想利用网络传输数据要先对IP地址进行转换(所传输的内容不需要转换,因为它们是被包装在数据包里的,是与底层协议无关的,在传输成功后可以被接收方拿出来直接使用),而这需要使用htonl()、htons()、ntohl()和ntohs()这四个函数进行主机字节顺序格式和网络字节顺序格式之间的转换。

        我们使用结构体in_addr来表示网络字节顺序格式的IP地址。

        而我们可以使用inet_addr()和inet_ntoa()函数实现点分法IP地址字符串和网络字节顺序格式IP地址之间的转换。

        对于面向连接的Socket通信过程我们以下图进行表示:

 

                                                服务器                                                                     客户机

 

                建立流式套接字,返回套接字号s(socket)

                套接字s与本地地址绑定(bind)

                通知TCP,服务器准备好接收连接(listen)

                等待客户端的连接(accept)                                             建立流式套接字,返回套接字号s(socket)

                建立连接,得到新的套接字,比如ns                                  将套接字s与远程主机连接(connect)

                在套接字ns上读写数据,直接结束(send,recv)            在套接字s上读写数据,直接结束(send,recv)

                关闭套接字ns(closesocket)                                            关闭套接字s,结束会话(closesocket)

                关闭最初的套接字s,结束服务(closesocket)

 

        这以上就是面向连接的Socket编程的服务端与客户端建立连接并进行数据交互的基本步骤。

        但是基本的Socket接口由于参数比较繁琐,而且各个函数的功能并不单一,很容易出错,我觉得使用C++ ACE库是一种比较好的选择,不仅封装了Socket函数而且提供了网络编程所需的各种并发处理机制、进程间通信机制和内存管理机制,唯一的缺点是太过于庞大,并且涉及到很多C++的高级特性而难以学习,所以选择何种编程方式需要权衡再做决定。

你可能感兴趣的:(socket,编程,网络,windows,网络协议,unix)