在前面的文章中有一篇讲到了命名管道通信,它是创建一根管道来进行进程之间或网络之间通信的。但是它有些缺陷,比如说效率较低等。而从这篇文章开始将介绍socket编程。socket是通过TCP,UDP,IP协议来进行通信,效率较高。本文先介绍TCP的服务端和客户端。
TCP是面向连接的,它在进行通信之前呢,需要双方先进行沟通,然后才能进行通信。而且TCP是以数据流的方式进行数据传递,会自动的进行拆包和组包的过程。所以呢,TCP的连接是比较可靠的,但是它的传输速度也因此相对较慢。接下来看下如何在代码中实现TCP的通信。
在windows中,要想进行socket网络操作,必须包含一个名叫做WinSock2.h(或者WinSock.h),如果包含的是WinSock2.h则必须在windows.h之前,否则会产生一些重定义的编译错误。包含完头文件之后,还要链接一个库文件ws2_32.lib,完成之后,我们就可以开始进行TCP服务端和客户端的编写了。
先来看服务端。首先,要进行网络操作,我们先要进行一下网络环境的初始化。WSAStartup函数就是用来初始化网络环境的。其声明如下:
int WSAStartup(
WORD wVersionRequested, //版本号,一般使用2.2版本
LPWSADATA lpWSAData <span style="white-space:pre"> </span>//WSAData地址
);
上面函数的第二个参数,接收一个WSAData结构的指针,该结构呢,里边包含了版本号,我们传递的版本号会对该结构里边的版本号进行初始化。
初始化完成之后,我们需要创建一个socket(套接字),这个套接字相当于我们前面讲到的管道,用于客户端和服务端的连接。调用socket函数我们可以创建一个套接字,声明如下:
SOCKET socket(
int af, //IP协议簇
int type, //套接字类型,TCP应该用SOCK_STREAM
int protocol<span style="white-space:pre"> </span> //协议
);
其实,socket也是一个内核对象,但是它没有内核对象所拥有的明显标志,安全属性。
创建好套接字后呢,我们需要告诉操作系统需要在哪个地址和端口上进行网络操作,相当于管道通信中绑定到标准输入输出口上。绑定的时候,需要有一个SOCKADDR_IN这个结构体,声明如下:
struct sockaddr_in{
short sin_family;<span style="white-space:pre"> </span>//协议簇
unsigned short sin_port;<span style="white-space:pre"> </span>//端口
struct in_addr sin_addr;<span style="white-space:pre"> </span>//ip地址
char sin_zero[8];<span style="wh