之前写过socket编程的原理 , 正好高级网络实验课要写socket程序,故总结一下实践中的一些问题。
Winsock实现
由于我的系统是windows,所以采用Winsock接口。
MFC提供了两个类用以封装Windows Sockets API
- CAsyncSocket类:具有一定网络编程经验的开发人员
- CSocket类:由CAsyncSocket类派生,简化网络编程
需要包含Winsock2.h,Winsock32.dll和ws2_32.lib
端口选择:端口1024以前的端口号都是系统保留的或是作为公共服务的,应尽量选择大于1024的端口号
WinSock初始化
Windows 下的 socket 程序依赖 Winsock.dll 或 ws2_32.dll,必须提前加载。
调用任何一个Winsock函数之前都必须检查协议栈安装情况,使用函数WSAStartup() 调用winsock DLL
1 |
|
创建套接字
当type指定为SOCK_STREAM或SOCK_DGRAM时,因为系统已明确使用tcp和udp来工作,protocol可指定为0
1 |
|
编译时报错:Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
问题的解决:
1、用所提示的新函数代替inet_addr函数。
2、修改VS配置,告诉它我就要旧函数,修改方法:项目->属性->C/C++->常规->SDL检查,将“是”改为“否”,即可
主机序与网络字节序
主机序:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序。分为大端和小端两种方式
测试主机序
1 |
|
本机测试结果为:小端序
网络字节序:TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。
于是,在数据处理时涉及到字节顺序转换的问题。这里用inet_addr
htons
处理
绑定端口(服务器)
1 | /*绑定套接字和端口 */ |
监听端口(服务器)
1 | /* 监听连接请求 */ |
发起连接(客户端)
在客户端使用connect请求建立连接时,将激活建立连接的三次握手,用来建立一条到服务器TCP的连接。
1 | /* 发起连接请求*/ |
处理连接请求(服务器)
accept用于面向连接的服务器端,在IP协议族中,只用于TCP服务器端
accept接受一个socket的连接请求,同时返回一个新的socket,新的socket用来在服务器与客户端之间传递和接收信息
此时socket表示处于监听状态的socket,地址是客户机的IP地址
1 | /*阻塞等待客户端发起连接,三次握手成功建立连接后会返回一个新的文件描述符指向客户端socket,用于真正数据传输*/ |
获取客户端的数据并处理(服务器)
1 | // 客户端 |
关闭套接字
1 | //关闭套接字 |
Linux实现
Windows 下的 socket 程序和 Linux 思路相同,但细节有所差别:
1) Windows 下的 socket 程序依赖 Winsock.dll 或 ws2_32.dll,必须提前加载。
2) Linux 使用“文件描述符”的概念,而 Windows 使用“文件句柄”的概念;Linux 不区分 socket 文件和普通文件,而 Windows 区分;Linux 下 socket() 函数的返回值为 int 类型,而 Windows 下为 SOCKET 类型,也就是句柄。
3) Linux 下使用 read() / write() 函数读写,而 Windows 下使用 recv() / send() 函数发送和接收。
4) 关闭 socket 时,Linux 使用 close() 函数,而 Windows 使用 closesocket() 函数。
服务器端
1 |
|
客户端
1 |
|