套接字编程

Linux下的ipc通信

管道
消息队列
共享内存
信号量
套接字

具体讲解
由于其中没有套接字的信息,现补充如下

套接字(socket)
socket是什么

socket是计算机之间进行通信的一种约定或者一种方式
通过socket这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据,这也就实现了计算机间的通信。
socket原意是“插座”,计算机通信领域是“套接字”,把插头插到插座上就可以从电网中获取电力,同理,为了与其他计算机进行数据传输,需要连接到因特网,而socket就是链接因特网的工具。
socket的典型应用就是Web服务器和浏览器,浏览器获取用户输入的URL,向服务器发起请求,服务器分析接收到的URL,将对应的网页内容返回给浏览器,浏览器再经过解析和渲染,将文字、图片、视频等元素呈现给用户。

Linux中的socket是什么

因为在Linux下万物皆文件,所以网络连接也是一个文件,故其也有文件描述符。
Linux下可以通过socket()函数创建一个网络连接,即打开一个网络连接文件,socket()的返回值就是文件描述符。
有了文件描述符,就可以使用普通文件操作函数进行收发数据了,read()、 write()、 send()、 receive()。

Window中的socket是什么

Windows虽然没有文件描述符,但有文件句柄。操作者都可以通过二者来找到唯一且符合操作者预期的事物。
与Linux不同,Windows会区分socket和文件,Windows认为socket就是一个网络连接,需要专门针对socket而设计的数据传输函数,针对普通文件的输入输出函数就无效了。

套接字类型

根据数据的传输方式,可以将 Internet 套接字分成两种类型流格式套接字和数据报格式套接字

流格式套接字(SOCK_STREAM)

流格式套接字(Stream Sockets)也叫“面向连接的套接字”,即SOCK_STREAM。

SOCK_STREAM是一种可靠的、双向的通信数据流,数据可以准确无误地到达另一个计算机,如果损坏或者丢失,可以重新发送

SOCK_STREAM的特征:

  1.安全性,数据在传输过程中不会消失

  2.次序性,数据是按照顺序传输的

  3.非同步,数据的发送和接收不是同步的

可以将SOCK_STREAM比喻成一条传送带,只要传送带本身没有问题(未断网),就可以保证数据不会丢失,同时较晚传送的数据不会先到达,较早传送的数据不会晚到达,这就保证了数据是按照顺序传递的

至于为什么SOCK_STREAM可以保证高质量的数据传输,正是因为它使用了TCP协议

关于“数据的发送和接收不同步”的理解下面举例说明:

假设传送带传送的是水果,接收者需要凑齐 100 个后才能装袋,但是传送带可能把这 100 个水果分批传送,
比如第一批传送 20 个,第二批传送 50 个,第三批传送 30 个。
接收者不需要和传送带保持同步,只要根据自己的节奏来装袋即可,不用管传送带传送了几批,也不用每到一批就装袋一次,可以等到凑够了 100 个水果再装袋。

流格式套接字的内部有一个缓冲区(也就是字符数组),通过 socket 传输的数据将保存到这个缓冲区。
接收端在收到数据后并不一定立即读取,只要数据不超过缓冲区的容量,接收端有可能在缓冲区被填满以后一次性地读取,也可能分成好几次读取。

也就是说,不管数据分几次传送过来,接收端只需要根据自己的要求读取,不用非得在数据到达时立即读取。
传送端有自己的节奏,接收端也有自己的节奏,它们是不一致的。

SOCK_STREAM的使用场景,浏览器所使用的http协议就是基于SOCK_STREAM,因为必须确保数据的准确无误,否则加载的HTNL将无法解析

数据报格式套接字(SOCK_DGRAM)

数据报格式套接字(Datagram Sockets)也叫“无连接的套接字”,即SOCK_DGRAM。

SOCK_DGRAM只管传输数据,不作数据校验,如果数据在传输中损坏,或者没有到达另一台计算机,是没有补救办法的。也就是说,数据丢了就丢了,没办法重传,也没有补救的办法。
但正是因为这个SOCK_DGRAM所做的校验工作少,所以它在传输效率方面比SOCK_STREAM高。

SOCK_DGRAM的特征:

  1.传输快速,数据传输快速但传输顺序就无法保证

  2.可能丢包,传输的数据可能会丢失或者损坏

  3.数据大小,每次传输的数据有大小限制

  4.数据同步,数据的发送和接收是同步的

ege:
众所周知,速度是快递行业的生命。
用摩托车发往同一地点的两件包裹无需保证顺序,只要以最快的速度交给客户就行。
这种方式存在损坏或丢失的风险,而且包裹大小有一定限制。
因此,想要传递大量包裹,就得分配发送。


另外,用两辆摩托车分别发送两件包裹,
那么接收者也需要分两次接收,所以“数据的发送和接收是同步的”;
换句话说,接收次数应该和发送次数相同。

总之,数据报套接字是一种不可靠的、不按顺序传递的、以追求速度为目的的套接字。

SOCK_DGRAM 使用的UDP协议,这也是它无法保证可靠传输的原因。

SOCK_DGRAM的使用场景,QQ视频聊天、语音聊天,因为在上述使用场景中,需要先保证通信的及时性,减少延迟,而数据正确性反而是次要的,即使丢失一部分数据,也不影响视频和音频的正常解析,最多出现一些噪音或者杂音,并不会对通信质量有实质的影响。

还有SOCK_DGRAM虽然会丢包,但只是小概率事件,并不会频繁的丢包,只是相比于TCP他不可靠而言,并不是它本身不可靠。
  

socket示例说明
服务端server.cpp:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(){
    //创建套接字
    int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    //将套接字和IP、端口绑定
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
    serv_addr.sin_family = AF_INET;  //使用IPv4地址
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
    serv_addr.sin_port = htons(1234);  //端口
    bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    //进入监听状态,等待用户发起请求
    listen(serv_sock, 20);
    //接收客户端请求
    struct sockaddr_in clnt_addr;
    socklen_t clnt_addr_size = sizeof(clnt_addr);
    int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
    //向客户端发送数据
    char str[] = "http://c.biancheng.net/socket/";
    write(clnt_sock, str, sizeof(str));
   
    //关闭套接字
    close(clnt_sock);
    close(serv_sock);
    return 0;
}

客户端client.cpp
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
int main(){
    //创建套接字
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    //向服务器(特定的IP和端口)发起请求
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
    serv_addr.sin_family = AF_INET;  //使用IPv4地址
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
    serv_addr.sin_port = htons(1234);  //端口
    connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
   
    //读取服务器传回的数据
    char buffer[40];
    read(sock, buffer, sizeof(buffer)-1);
   
    printf("Message form server: %s\n", buffer);
   
    //关闭套接字
    close(sock);
    return 0;
}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值