先贴源码:
For Server:
For Client:
运行结果如下:
先行运行服务端,它会提示绑定成功,并等待客户端连接:
运行客户端后双方开始进行互发消息:
分析与对比:
Socket大致流程如下图所示
对于服务端而言,它的流程就是
创建socket --->> 绑定socket和端口号 --->>监听该端口号 --->>等待来自客户端的连接请求 --->> 接受消息或发送消息
而客户端这是:
创建socket --->> 连接指定的服务器的端口 --->> 接受消息或发送消息
当连接结束后,两者都要记得关闭socket。
但是我们在分析老师在课上写的linux socket 使用 #include <sys/socket.h>
和上叙写的C++ 使用 #include <winsock.h>的流程也是相似的
非要说区别可能就是 winsock编程前 需要初始化WSAStartup
对应的退出清理需要使用WSAClearup( )
以及一些函数名字的区别 如closesocket( ) 和 Linux 下的close ( )
接下来着重分析socket API
1、socket
它有三个参数,分别是domin、type 和 protocol,即协议域、socket类型和协议
同时我们也可以在winsock.h头文件中找到对应的宏定义:
Domin :协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合。
protocol:协议就是我们学过的tcp、udp等等
2、bind
在socket描述符创建初始化之后,便需要使用bind ( )把一个地址族中的特定地址赋给socket
如图,利用SOCKADDR_IN 定义变量并设置好对应的协议和端口号之后,紧接着调用bind( )函数将其绑定在socket中
故bind函数的三个参数是 socket 、 一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址 和 地址长度
图中我们使用的是AF_INET即ipv4协议,那么对应的协议地址结构如下:
3、listen
socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。
如果作为一个服务器,在调用socket()、bind()之后就会调用listen()来监听这个socket。
第一个参数socket
第二个参数表示相应的socketk可以排队的最大连接个数
4、connect
从图中可以看出,connect( ) 函数的参数列表和 bind( )函数很相似
但它用于客户端,客户端调用connect ()函数来与服务器发出连接,这时服务器的listen( )函数便会收到它的连接请求
5、accept
服务器端依次调用socket()、bind()、listen()之后,就会监听指定的socket地址了。
而客户端依次调用socket()、connect()之后就等于是向服务器发送了一个连接请求,这时服务器可以使用accept( )来接受这个请求。
它的参数列表依旧和bind( )类似,但是中间的addr地址返回的是客户端的协议地址,而bind()的addr地址是指向要绑定的socket的协议地址。
6、recv 和 send
即发送和接收
7、close
当所有的操作完成后,需要使用closesockt()来关闭所有的连接。