简单理解Socket



TCP/IP

要想理解socket首先得熟悉一下TCP/IP协议族, TCP/IPTransmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,定义了主机如何连入因特网及数据如何再它们之间传输的标准,

从字面意思来看TCP/IP是TCP和IP协议的合称,但实际上TCP/IP协议是指因特网整个TCP/IP协议族。不同于ISO模型的七个分层,TCP/IP协议参考模型把所有的TCP/IP系列协议归类到四个抽象层中

应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等

传输层:TCP,UDP

网络层:IP,ICMP,OSPF,EIGRP,IGMP

数据链路层:SLIP,CSLIP,PPP,MTU

每一抽象层建立在低一层提供的服务上,并且为高一层提供服务,看起来大概是这样子的

                       

估计有兴趣打开此文的同学都对此有一定了解了,加上我也是一知半解,所以就不详细解释,有兴趣同学可以上网上搜一下资料

维基百科

百度百科

在TCP/IP协议中两个因特网主机通过两个路由器和对应的层连接。各主机上的应用通过一些数据通道相互执行读取操作


socket

我们知道两个进程如果需要进行通讯最基本的一个前提能能够唯一的标示一个进程,在本地进程通讯中我们可以使用PID来唯一标示一个进程,但PID只在本地唯一,网络中的两个进程PID冲突几率很大,这时候我们需要另辟它径了,我们知道IP层的ip地址可以唯一标示主机,而TCP层协议和端口号可以唯一标示主机的一个进程,这样我们可以利用ip地址+协议+端口号唯一标示网络中的一个进程。

能够唯一标示网络中的进程后,它们就可以利用socket进行通信了,什么是socket呢?我们经常把socket翻译为套接字,socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。

socket起源于UNIX,在Unix一切皆文件哲学的思想下,socket是一种"打开—读/写—关闭"模式的实现,服务器和客户端各自维护一个"文件",在建立连接打开后,可以向自己文件写入内容供对方读取或者读取对方内容,通讯结束时关闭文件。

socket通信流程

socket是"打开—读/写—关闭"模式的实现,以使用TCP协议通讯的socket为例,其交互流程大概是这样子的

服务器根据地址类型(ipv4,ipv6)、socket类型、协议创建socket

服务器为socket绑定ip地址和端口号

服务器socket监听端口号请求,随时准备接收客户端发来的连接,这时候服务器的socket并没有被打开

客户端创建socket

客户端打开socket,根据服务器ip地址和端口号试图连接服务器socket

服务器socket接收到客户端socket请求,被动打开,开始接收客户端请求,直到客户端返回连接信息。这时候socket进入阻塞状态,所谓阻塞即accept()方法一直到客户端返回连接信息后才返回,开始接收下一个客户端谅解请求

客户端连接成功,向服务器发送连接状态信息

服务器accept方法返回,连接成功

客户端向socket写入信息

服务器读取信息

客户端关闭

服务器端关闭

三次握手

在TCP/IP协议中,TCP协议通过三次握手建立一个可靠的连接

第一次握手:客户端尝试连接服务器,向服务器发送syn包(同步序列编号Synchronize Sequence Numbers),syn=j,客户端进入SYN_SEND状态等待服务器确认

第二次握手:服务器接收客户端syn包并确认(ack=j+1),同时向客户端发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态

第三次握手:第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手

定睛一看,服务器socket与客户端socket建立连接的部分其实就是大名鼎鼎的三次握手

 socket编程API

前面提到socket是"打开—读/写—关闭"模式的实现,简单了解一下socket提供了哪些API供应用程序使用,还是以TCP协议为例,看看Unix下的socket API,其它语言都很类似(PHP甚至名字都几乎一样),这里我就简单解释一下方法作用和参数,具体使用有兴趣同学可以看看博客参考中的链接或者上网搜索

int socket(int domain, int type, int protocol);

根据指定的地址族、数据类型和协议来分配一个socket的描述字及其所用的资源。

domain:协议族,常用的有AF_INET、AF_INET6、AF_LOCAL、AF_ROUTE其中AF_INET代表使用ipv4地址

type:socket类型,常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等

protocol:协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

把一个地址族中的特定地址赋给socket

sockfd:socket描述字,也就是socket引用

addr:要绑定给sockfd的协议地址

addrlen:地址的长度

通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。

int listen(int sockfd, int backlog);

监听socket

sockfd:要监听的socket描述字

backlog:相应socket可以排队的最大连接个数 

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

连接某个socket

sockfd:客户端的socket描述字

addr:服务器的socket地址

addrlen:socket地址的长度

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

 TCP服务器监听到客户端请求之后,调用accept()函数取接收请求

sockfd:服务器的socket描述字

addr:客户端的socket地址

addrlen:socket地址的长度

ssize_t read(int fd, void *buf, size_t count);

读取socket内容

fd:socket描述字

buf:缓冲区

count:缓冲区长度

ssize_t write(int fd, const void *buf, size_t count);

向socket写入内容,其实就是发送内容

fd:socket描述字

buf:缓冲区

count:缓冲区长度

int close(int fd);

socket标记为以关闭 ,使相应socket描述字的引用计数-1,当引用计数为0的时候,触发TCP客户端向服务器发送终止连接请求。

参考

Linux Socket编程(不限Linux)

揭开Socket编程的面纱

PS. 有同学看完后发现没有demo示例,参考中的示例已经很不错了,我就不班门弄斧了,而且我用C#实现了一个websocket server,接下来的博客中会有介绍。另外由于刚刚实际接触socket,文中谬误较多,还望大家批评指正,文章内容主要参考上面两个博文,图片全部来源于网络,在百度图片搜索得来,无法注明第一源地址,如有版权问题请站内信联系,第一时间处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/405364.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

女人必知:10个好习惯 让老公不想出轨

阅读提示:要知道,妻子这10个动作是征求了数百名老公的意见之后进行总结得出的,不仅效果显著,杀伤力强,最关键的是简单易行。女人必知:10个好习惯 让老公不想出轨  1.老公累了,靠在沙发上睡了&…

codeforce Gym 100500F Door Lock (二分)

根据题意略推一下&#xff0c;其实就是问你满足(a*(a1))/2 < m < ((a1)*a(a2))/2的a和m-(a*(a1))/2 -1是多少。 二分求解就行了 #include<cstdio>using namespace std; typedef long long ll;int main() {int T;scanf("%d",&T);for(int k 1; k <…

write() vs. writev()

From: http://www.cppblog.com/whoami17/archive/2009/05/10/82452.html 今天突然想比较一下 write() 和 writev() 的性能&#xff0c; 网上google了半天&#xff0c; 竟然没有发现一点有关的数据信息&#xff0c; 自己就测试了一下。 平台如下&#xff1a; CentOS 5.2 Lin…

[react] React Intl是什么原理?

[react] React Intl是什么原理&#xff1f; 实现原理和react-redux的实现原理类似&#xff0c;最外层包一个Provider&#xff0c;利用getChildContext&#xff0c;将intlConfigPropTypes存起来&#xff0c;在FormattedMessage、FormattedNumber等组件或者调用injectIntl生成的…

linux下GPRS模块ppp拨号上网

&#xfeff;&#xfeff;交叉编译器&#xff1a;arm-linux-gcc-4.5.4 Linux内核版本&#xff1a;Linux-3.0 主机操作系统&#xff1a;Centos 6.5 开发板&#xff1a;FL2440 GPRS:SIM900A 在开发SIM900模块之前&#xff0c;开发板已经加载了linux内核以及文件系统&#xf…

Linux 使用sigaction查询或设置信号处理方式

一、概述 Linux的系统调用函数sigaction()可以用来查询或设置信号处理方式。 函数声明为&#xff1a; #include <signal.h>int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 如果执行成功返回0&#xff0c;否则返回-1。其中&…

mysql replicate error

工作日志之-MySQL slave Replication ErrorDescription&#xff1a; mysql> start slave;ERROR 1201 (HY000): Could not initialize master info structure; more error messages can be found in the MySQL error log [rootslave ~]# tail /var/log/mysqld.log 090105 11:…

高级I/O(七)--readv和writev函数

From: http://blog.chinaunix.net/uid-26822401-id-3158225.html readv和write函数让我们在单个函数调用里从多个不连续的缓冲里读入或写出。这些操作被称为分散读&#xff08;scatter read&#xff09;和集合写&#xff08;gather write&#xff09;。 #include <sys/uio…

CABasicAnimation动画

使用CABasicAnimation动画: CALayer *znzLayer; [[CALayer alloc]init]; //创建不断该表CALayer的transform属性动画CABasicAnimation *anim [CABasicAnimation animationWithKeyPath:"transform"];CATransform3D fromValue znzLayer.transform;//设置动画开始的属…

linux pppd脚本配置

&#xfeff;&#xfeff;摘要本文主要介绍了嵌入式Linux系统下使用pppd 2.4.4来进行PPP拨号需要使用的脚本是如何配置的&#xff0c;配置项的含义&#xff0c;同时也说明了如何来配置参数&#xff0c;实现ppp拨号上网。一&#xff0e;问题提出嵌入式Linux操作系统下&#xff…

React面试题目录汇总

总29 2021年11月10日&#xff08;更12&#xff09; [react] 什么时候使用状态管理器&#xff1f; [react] render函数中return如果没有使用()会有什么问题&#xff1f; [react] componentWillUpdate可以直接修改state的值吗 [react] 什么渲染劫持&#xff1f; [react] 说…

Linux运行可执行文件

原先以为linux下运行可执行文件在文件名前加"./"是执行命令&#xff0c;今天才搞明白是指当前目录转载于:https://www.cnblogs.com/dpc525/archive/2011/04/25/2028715.html

Linux下如何定位Java进程CPU利用率过高原因

首先通过Top命令查看占用CPU较高的进程PID&#xff0c;执行Top之后按1可以查看每个核占用比例 1 top这里由于我是用的虚拟机&#xff0c;即使我的Java进程占用CPU很高也只是占的虚拟机的&#xff0c;而对整个机器的CPU来说占的并不高。这里我们找到了pid7957 然后我们在根据pi…

在用户态下使用uint64_t

#include <stdio.h> #include <stdint.h>typedef struct {unsigned short msg_type;unsigned short msg_len;//msg body len }st_msg_h;typedef struct{char audio_name[64];uint64_t time_stamp;//输入的要播放的时间戳绝对时间int dec_ch;}st_msg_start;typedef …

【iOS开发】企业版证书($299)In-House方式发布指南

一、明确几个概念 1、企业版IDP&#xff1a;即iOS Development Enterprise Program。注意是$299&#xff0f;Year那种&#xff0c;并不是$99/Year的那种。 2、In House&#xff1a;是只企业内部发布&#xff0c;仅限企业内部人员使用。 二、In-House方式特点 1、不能发布到Appl…

[react] 说说你对windowing的了解

[react] 说说你对windowing的了解 展示长列表 如果你的应用会渲染大量的列表数据&#xff0c;我们建议使用一种称为‘windowing’的技术&#xff0c;这种技术下在任何给定的时间内只会渲染一小部分数据列表&#xff0c;并可以减少列表项的重复渲染&#xff08;即再次渲染已经渲…

ARM 移植 PPPD

&#xfeff;&#xfeff;1&#xff0e; 下载编译ppp-2.4.1 a) 解压 b) 进入chat目录&#xff0c;修改Makefile.Linux, 添加CCarm-linux-gcc c) 编译chat: make –f Makefile.linux,生成chat d) 进入pppd目录&#xff0c;修改Makefile.linux, 将CCgcc…

回车(CR)与换行(LF), '\r'和'\n'的区别

一&#xff1a;回车”&#xff08;Carriage Return&#xff09;和“换行”&#xff08;Line Feed&#xff09;起源 首先&#xff0c;弄清两个概念&#xff1a; 回车CR-将光标移动到当前行的开头。 换行LF-将光标“垂直”移动到下一行。&#xff08;而并不移…

Linux shell逐行读取文件的方法-比较

From: http://www.embeddedlinux.org.cn/html/jishuzixun/201211/19-2387.html 在linux中有很多方法逐行读取一个文件的方法&#xff0c;其中最常用的就是下面的脚本里的方法&#xff0c;而且是效率最高&#xff0c;使用最多的方法。为了给大家一个直观的感受&#xff0c;我们…

RMSE、MAPE、准确率、召回率、F1、ROC、AUC总结

RMSE(root mean square error)均方根误差 单纯统计误差的值。 MAPE(mean absolute percentage error) 平均百分比误差 存在一个和原始数据相比较的过程。 准确率&#xff08;precision&#xff09;P&#xff1a; PTP/(TPFP) TP(true positive) FP(false positive) P是代表预…