文章目录
- 一、Socket概述
- 二、Socket API 概述
- 三、WinSock常用API
- 3.1 常用API
- 3.1.1 WSAStartUP
- 3.1.2 WSACleanup
- 3.1.3 Socket
- 3.1.4 Closesocket
- 3.1.5 bind
- 3.1.6 listen
- 3.1.7 connect
- 3.1.8 accept
- 3.1.9 send, sendto
- 3.1.10 recv, recvfrom
- 3.1.11 etsockopt, getsockopt
- 3.2 网络字节顺序
- 四、客户端软件设计
- 4.1 解析
- 4.1.1 解析IP
- 4.1.2 解析端口号
- 4.1.3 解析协议号
- 4.2 连接流程
- 4.2.1 TCP
- 4.2.2 UDP
- 五、服务端软件设计
- 5.1 循环无连接 iterative connectionless
- 5.2 循环面向连接 Iterative connection-oriented
- 5.3 并发无连接 Concurrent connectionless
- 5.4 并发面向连接 Concurrent connection-oriented
一、Socket概述
Socket(套接字)是一种计算机网络通信机制,它提供了一种统一的编程接口,使得应用程序可以通过网络进行数据传输和通信。在计算机网络中,Socket通常指的是TCP/IP协议栈中的Socket,也就是套接字接口。
Socket具有以下主要作用:
建立连接:Socket提供了客户端与服务器建立网络连接的机制,使得数据可以在不同计算机之间进行传输。
传输数据:Socket提供了数据读写操作的接口,使得应用程序可以通过网络发送和接收数据。
关闭连接:Socket提供了关闭连接的接口,使得已经建立的网络连接可以被释放和关闭。
在OSI七层模型中,Socket位于第四层(传输层),负责处理端到端的数据传输和可靠性。它能够在网络上建立虚拟通道,保证应用程序之间数据的可靠传输,从而实现网络通信和数据交换。
总之,Socket作为一种通用的网络编程接口,为应用程序提供了方便的网络通信功能,是计算机网络中非常重要的组成部分。
应用编程接口API:就是应用进程的控制权和操作系统的控制权进行转换的一个系统调用接口
- Berkeley UNIX 操作系统定义了标准API,称为 套接字接口(socket interface) 简称套接字Socket,Linux也是用此标准接口
- Windows用的是在Socket interface之上封装的API:Windows Socket Interface(WINSOCK)
- AT&T 为其UNIX系统V定义了一种API,简写为TLI(Transport Layer Interface)
二、Socket API 概述
- 最初设计
- 面向BSD UNIX-Berkley
- 面向TCP/IP协议栈接口
- Internet网路应用最典型的API接口
- 通讯模型C/S
- 应用进程之间通信的抽象机制
-
标识通信的段端点(对外):IP+端口
-
操作系统/系统如何管理套接字(对内)
- 套接字描述符socket descripotor
-
在UNIX中,OS是把socket当做文件统一管理
-
进程创建Socket时,OS分配一个 数据结构 存储Socket相关信息
Socket数据结构
struct sockaddr_in{
u_char sin_len; /*地址长度 */
u_char sin_family; /*地址族(TCP/IP:AF_INET) ,用来面向其他协议栈*/
u_short sin_port; /*端口号 */
struct in_addr sin_addr; /*IP地址 */
char sin_zero[8]; /*未用(置0) */
}
三、WinSock常用API
WSA:Windows Socket Api,和标准API类似,就是在前面加上了WSA,其他基本类似
3.1 常用API
3.1.1 WSAStartUP
使用Socket之前必须首先调用WSASrartUP
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
//wVersionRequested:WinSock的版本,16进制参数
//lpWSAData:返回实际WinSock的版本信息
使用2.1版本的WinSock的程序代码段
wVersionRequested = MAKEWORD( 2, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
3.1.2 WSACleanup
完成对请求的Socket库的使用,最后要调用WSACleanup函数
- 解除与Socket库的绑定
- 释放Socket所占系统资源
int WSACleanup (void);
3.1.3 Socket
sd = socket(protofamily,type,proto);
//protofamily:协议族 protofamily = PE_INET(TCP/IP)
//type:套接字类型:type = SOCK_STREAM(TCP) / SOCK_DGRAM(UDP) / SOCK_RAW(TCP/IP)
//proto:协议号,默认为0
struct protoent *p;
p=getprotobyname("tcp");
SOCKET sd=socket(PF_INET,SOCK_STREAM,p->p_proto);
- 创建Socket
- 返回OS的套接字描述符 sd
type:套接字类型:type =
- SOCK_STREAM 流式 面向TCP
- SOCK_DGRAM 数据报式 面相DUP
- SOCK_RAW 直接跨越传输层 创建面向IP的协议,需要特殊权限root
3.1.4 Closesocket
int closesocket(SOCKET sd);
// UNIX:close()
//关闭一个描述符为sd的Socket
//多个进程共享一个套接字,调用close 引用数-1,到0才结束
//一个进程中,多个线程共用一个socket ,无计数,调用closesocket,全部关闭
//return 0 成功关闭
3.1.5 bind
int bind(sd,localaddr,addrlen);
//绑定套接字的本地端点地址 IP+端口
//参数sd:socket 标识符 localaddr:端点结构地址
//地址通配符:INADDR_ANY
3.1.6 listen
Server端调用,置监听状态,仅用于面向连接的流套接字TCP
int listen(sd,queuesize);
//queuesize设置连接请求 队列 的大小
// 0:成功
3.1.7 connect
仅用于客户端,
调用connect函数来使客户端套接字sd于服务端saddr连接
TCP UDP 都可以
- TCP:建立TCP连接
- UDP:不会建立连接,只会指定服务器端点地址
connect(sd,saddr,saddrlen);
3.1.8 accept
newsock = accept(sd,caddr,caddrlen);
3.1.9 send, sendto
send:TCP套接字 或 调用了 connect函数的UDP客户端套接字
sendto:UDP 中 未调用 connect函数的UDP套接字
send(sd,*buf,len,flags);
sendto(sd,*buf,len,flags,destaddr,addrlen);
3.1.10 recv, recvfrom
recv(sd,*buffer,len,flags);
recvfrom(sd,*buf,len,flags,senderaddr,saddrlen);
recv:TCP or UDP(调用了connect)
recvfrom:UDP(未调用connect)
3.1.11 etsockopt, getsockopt
int setsockopt(int sd, int level, int optname, *optval, int optlen);
int getsockopt(int sd, int level, int optname, *optval, socklen_t *optlen);
setsockopt:设置套接字sd选项参数
getsockopt:获取任意类型、任意状态 接口 的选项当前值,结果存入optval
3.2 网络字节顺序
网络字节顺序:network byte order
定义了标准的用于协议头中的二进制整数表示
某些Socket API函数的参数需要存储为网络字节顺序:IP 端口
+ htons:本地字节顺序----> 网络字节顺序 16bits
+ ntohs:网络字节顺序----> 本地字节顺序 16bits
+ htonl:本地字节顺序----> 网络字节顺序 32bits
+ ntohl:网络字节顺序----> 本地字节顺序 32bits
四、客户端软件设计
4.1 解析
4.1.1 解析IP
- inet_addr() :10进制IP ---- > 32IP地址
- gethostbyname(): 域名 -----> 32IP地址,返回一个hostent的指针
4.1.2 解析端口号
getservbyname() : 返回一个指向结构servent的指针
4.1.3 解析协议号
getprotobyname() : 返回一个指向结构protoent的指针
4.2 连接流程
4.2.1 TCP
- 确定IP:prot
- 创建Socket
- 分配本地端点地址 IP+Port
- 链接服务器Socket
- 遵循应用层协议进行通信
- 关闭/释放连接
4.2.2 UDP
- 确定IP:port
- 创建socket
- 分配本地端点地址 ip + prot
- 指定服务器端点地址,构造UDP数据报
- 遵循应用层协议进行通信
- 关闭/释放连接
五、服务端软件设计
5.1 循环无连接 iterative connectionless
- 创建Socket
- 绑定端点地址 INADDR + Port
- 反复接受来自客户端请求
- 遵循应用层协议,构造相应报文,发送给客户