学习编程的,不能不知道套接字—Socket,网络程序必备。对于一些初学者来说,可能一脸懵逼,挠头三连:这是个啥?怎么用?原理是啥?今天就了解一下套接字。
1.什么是 Socket?
Socket,译为“套接字”,是计算机之间通信的一种约定。通过 Socket,网络中的计算机之间可以相互收发信息。
socket 的典型应用就是 Web服务器和浏览器:浏览器输入URL->向服务器发送请求->服务器分析URL->返回Html页面给浏览器->浏览器进行渲染将网页呈现给用户。
socket 在LInux下,由于“Linux下一切皆文件”,因此socket也是一个网络连接套接字文件。既然是文件,也就有自己的文件描述符。 Windows下的 socket 被称为“文件句柄”,不同的是Windows下会区分 socket 和文件。因此在windows下需要专门调用针对 socket 而设计的数据传输函数—WSAStartup()和WSACleanup();
2.流式套接字和数据报套接字
流式套接字–SOCK_STREAM,又称“面向连接的套接字”,使用TCP协议。它是可靠、双向的通信数据流。
特征:
- 数据在传输过程中不会丢失
- 数据是按照顺序传输的
- 数据的发送和接收不同步
对于第三点的理解:流格式套接字的内部有一个缓冲区,通过 socket 传输的数据将保存到这个缓冲区。接收端在收到数据后并不一定立即读取,只要数据不超过缓冲区的容量,接收端有可能在缓冲区被填满以后一次性地读取,也可能分成好几次读取。
流式套接字主要应用于文件传输,因为文件需要全部、有效、有顺序的传输。
数据报套接字–SOCK_DGRAM,又称“无连接的套接字”,使用UDP协议。它是不可靠的、不按顺序传递的、以速度为目的。
特征:
- 速度快
- 传输的数据可能会丢失或损坏
- 每次传输时数据大小受到限制
- 数据的发送和接收同步
数据报套接字主要应用在视频和语音传输,及时丢失一部分数据,视频和音频仍然可以正确解析,不会对通讯质量有影响。
区别:
流式套接字表示数据以流的形式存在,上一个数据流与下一个数据流没有一个明显的分界线,也就是说你连续发来两个包,接受端可能只接受到一个,需要自己区分包的边界;
而数据报服务是以udp为代表,表明数据报与数据报之间有明显的分界线,发送方发送几个包,接受端就能接受到几个包,主要是一对一,一次发送对应一次接收,一次接收就必须要有一次发送。
3.如何使用 Socket?
以Linux为例
/****server***/
// 1.建立套接字
int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// 2.绑定端口号
bind(fd, (sockaddr*)&sockaddr_in, socklen_t);// bind函数用于将套接字文件描述符和网络端口号绑定起来,其第二个参数是含ip+port的一个结构体
// 3.监听
listen(fd, backlog); // backlog表示同一时刻的客户端最大连接数
// 4.接收
int cli_fd = accpet(fd, (sockaddr*)&sockaddr_in, &socklen_t); //返回一个客户端套接字描述符,后面两个参数是输出型参数,用于填充客户端的ip+port,**阻塞等待接收客户端连接到来**
// 5.给客户端发送数据
send(cli_fd, msg, msg_len, flag); // 最后一个参数为标志信息,一般为0
// 6.关闭套接字
close(fd);
close(cli_fd);
/****client***/
// 1.创建套接字
int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// 2.连接服务器
connect(fd, (sockaddr*)&sockaddr_in, socklen_t);
// 3.接收数据
recv(fd, buf, buf_size, flags); // 0表示阻塞接收,如果返回值<0,则报错返回,如果返回值=0,表示接收到消息为空
// 4.关闭套接字
close(fd);
client 运行后,通过 connect() 函数向 server 发起请求,处于监听状态的 server 被激活,执行 accept() 函数,接受客户端的请求,然后执行 send() 函数向 client 传回数据。client 接收到传回的数据后,connect() 就运行结束了,然后使用 recv() 将数据读取出来。
----文章来源于c.biancheng.net,整理得来