4-服务器程序编写
服务器程序编写
0.初始化网络库
WORD wVersionRequested; |
1.创建socket
1.1 socket
socket可以看成一个文件,向socket发送数据就是向其写入。也可以理解为一个网络连接,或者句柄。
SOCKET sockSrv; |
1.2向操作系统申请socket
调用socket函数,向操作系统申请一块内存,并将唯一编号返回给socket
-
af:使用的协议簇
- AF_UNIX:本机通信
- AF_INET :TCP/UDP ipv4
- AF_INET6:TCP/UDP ipv6
-
type:使用的套接字类型
- SOCK_STREAM(TCP流)
- SOCK_DGRAM(UDP数据报)
- SOCK_RAW(原始套接字)
-
protocol:在确定协议簇和套接字的情况下,默认为0。在不确定的情况下,可以用于确定协议的种类。
sockSrv = socket(AF_INET, SOCK_STREAM, 0); |
2.指定地址和端口
使用sockaddr_in,填充地址和端口
同时指定接收连接的IP地址可以是任意IP地址:INADDR_ANY(因为服务器可能有多个网卡,存在多个IP地址)(但客户端必须指定自己发送时的地址)
SOCKADDR_IN addrSrv; |
3.绑定
将对应的socket绑定上对应的sockaddr
注意:端口可能在bind时被占用,导致失败,在此做好错误检测的准备
bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); |
4.监听
当socket函数创建一个套接字时,该套接字被假设为一个主动套接字。在listen函数中,传入一个未连接的socket,将其转换为被动套接字,指示内核应接收指向该socket的连接请求。
第二个参数指定了内核为该socket排队的最大连接个数。
listen(sockSrv, 5); |
5.接收连接请求
当listen后,服务端socket里还有连接,则将队列头的连接通过accept来接收,并保存该连接对应的IP和端口信息,最后返回一个假设的客户端socket
注:accept函数是阻塞式的,在服务端连接队列为空时会一直等待(一定要先初始化网络库才行)
SOCKADDR_IN addrCli; //创建结构体,用于保存新的连接IP和端口 |
6.发送信息
使用send函数,向sockConn发送sendBuf里的信息,默认阻塞
注意,返回值<0出错,==0超时对方关闭连接,>0为发送数据大小
char sendBuf[100] = { 0 }; |
7.接收信息
使用recv函数,向sockConn接收信息到sendBuf里,默认阻塞
返回值<0出错,==0超时对方关闭连接,>0为接收数据大小
char recvBuf[100] = { 0 }; |
8.关闭连接
closesocket(sockConn); |
9.补充
对于每一种网络操作函数,都会返回一个数,如果这个数==SOCKET_ERROR,则出错,调用GetLastError()函数来返回对应的错误码。
由此可以利用宏定义来简化错误显示
案例
if (SOCKET_ERROR == send(fd, buf, strlen(buf), 0)) |
完整代码
|