socket 的基础知识(一)
来源:互联网 发布:java sendmail 发邮件 编辑:程序博客网 时间:2024/06/05 08:13
Socket 编程
计算机网络是相互连接的独立自主的计算机的集合,最简单的网络形式由两台计算机组成
IP地址
IP网络中每台主机都必须有唯一一个IP地址
IP地址是一个逻辑地址
因特网上的IP地址具有全球统一性
32位,4个字节,常用点分十进制的格式表示 192.168.0.23
协议:
为进行网络中的数据交换(通信)而建立的规则,标准或者约定
不同层有各自不同的协议
OSI七层
应用层 :处理网络应用
表示层 : 数据表示
会话层 : 主机间通信
传输层 :端到端的连接
网络层 : 寻址和最短路径
数据链路层 :介质访问
物理层 :二进制传输
OSI 各层所使用的协议
应用层:
远程登陆协议 Telent
文本传输协议 FTP
超文本传输协议 HTTP
域名服务 DNS
简单邮件传输协议 SMTP
邮局协议 POP3
传输层
传输控制协议:TCP
用户数据报协议:UDP
TCP:面向连接的可靠的传输协议
UDP:是无连接的,不可靠的传输协议
网络层
网际协议IP, Internet 互联网控制报文协议ICMP ,Internet 组管理协议IGMP
数据封装:一台计算机要发送数据到另一台计算机上,数据首先必须打包,打包的过程称为i封装。 封装就是在数据前面加上特定的协议头部
TCP/IP模型
包括四个层次:应用层,传输层,网络层,网络接口
端口:
传输层提供进程通信的能力,为了标识通信实体中进行通信的进程,TCP/IP协议提出了协议端口,简称端口
端口是一种抽象的软件结构(包括一些数据结构和I/O缓冲区),应用程序通过系统调用
与某端口建立连接(bind)之后,传输层传给该端口的数据被相应的进程所接收,相应进程发送给传输层的数据都由该端口输出
端口用一个整数型标示符来表示,即端口号,端口号跟协议相关,TCP/IP传输层的两个协议TCP/UDP 是完全独立的两个软件模块,因此各自的端口号也相互独立。
端口号用一个16位的数字表示,范围是0--65535
套结字(socket的引入)
Socket 使程序员可以很方便的访问TCP/IP,从而开发各种网络应用的程序
网络字节顺序:
不同的计算机存放多字节值的顺序不同,基于Intel 的CPU,即我们常用的pc机采用的是
低位先存,为保证数据的正确性,在网络协议中需要指定网络字节顺序,TCP/IP协议使用16位整数和32位整数的高位先存格式
客户端和服务器模式
1.在TCP/IP网络应用中,通信的两个进程间相互作用的主要模式是客户端/服务器模式,客户端向服务器提出请求,服务器接收到请求时,提供相应的服务
2.建立网络的起因:
(1)网络中软硬件资源,运算能力和信息不均等,需要共享,从而造就众多资源的主机提供服务,资源较少的客户请求服务这一非对等作用
(2)网络间的通信完全是异步的,相互通信的进程间不存在父子关系,又不存在共享内存缓冲区,因此需要一种机制为希望通信的进程间建立联系,为二者的数据交换提供同步。
客户端/服务器模式在操作过程中采用的是主动请求的方式
首先服务器方要先启动,并根据请求提供相应的服务
1.打开一通道并告知本地主机,它愿意在某一公认地址接收客户请求;
2.等待客户请求到达该端口
3.接收到重复请求服务,处理该请求并发送应答信号,接收到并发服务请求,要激活一新的进程来服务处理这个客户请求,新进程处理此客户请求,并不需要对其他请求作出应答,服务完成后,关闭此进程与客户的通信链路,并终止
4.返回第二步,等待另一客户请求
5.关闭服务器
客户端:
1.打开一通信通道,并连接到服务器所在的主机的特定端口
2.向服务器发送服务请求报文,等待并接收应答,继续提出请求
3.请求结束 后关闭通信通道并终止
总结:
1.服务器与客户端的进程的作用是非对称的,因此编码不同
2.服务进程一般是先于客户请求而启动的,只要系统运行,该服务 进程一直存在,直到正常或者被强迫终止
套接字的类型:
1.流式套结字(SOCK_STREAM)
提供面向连接,可靠的数据传输服务,数据无差错,无重复的发送,且按发送顺序接收
内设流量控制,避免数据流超限;数据被看作是字节流,无长度限制,文件传输协议(FTP)
用流式套接字
2.数据报套接字(SOCK_DGRAM)
提供无连接服务,数据包以独立包形式发送,不提供无错保证,数据可能重复或者丢失,并且接收顺序可能混乱,网络文件系统(NFS)使用数据报式套接字
3.原始套接字(SOCK_RAW)
该接口允许对于较低层协议,如IP,ICMP 直接访问,常用于检验新的协议实现或访问现有服务中配置的新设备
基于TCP的socket 编程
服务器:
1.创建套接字(socket)
2.将套接字绑定到一个本地地址和端口上(bind)
3.将套结字设置为监听模式,准备接收客户请求(listen)
4.等待客户端请求哦到来;当请求到来后,接收连接请求,返回一个对此次连接新的套接字(accept)
5.用返回的新的套接字与客户端进行通信
6.返回,等待另一用户请求
7.关闭套接字
客户端操作
1.创建套接字(socket)
2.向服务器发出连接请求(connect)
3.和服务器端进行通信(send/recv)
4.关闭套接字
基于UDP的socket
服务器:
1.创建套接字(socket)
2.J将套接字绑定到一个本地地址和端口上(bind)
3.等待接收数据(recvfrom)
4.关闭套接字
客户端:
1.创建套结字(socket)
2.向服务器发送数据(sendto)
3.关闭套接字
基于套接字系统调用
创建套结字--------socket()
int socket(int domain, int type, int protocol);
第一个参数指定通信发生的区域,UNIX系统支持的地址族有:AF_UNIX AF_INET
AF_US 而DOS, WINDOWS 中支持AF_INET
它是网际网区域,因此,地址族与协议族相同
第二个参数是要创建的套接字的类型
第三个参数说明该套接字使用的协议,如果调用者不希望特别指定使用的协议,则置为0
使用默认的连接模式 ,根据这三个参数建立一个套接字,并将相应的资源分配给它,同时返回一个整型套接字号。
指定本地地址-------bind()
当一个套接字用socket()创建之后,存在一个名字空间(地址族),但它没有被命名,bind()将套接字地址与所创建的套接字号联系起来,即将名字赋与套接字,以指定本地半相关。
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
第一个参数是socket()调用返回的并且未作连接的套接字描述符
第二个参数是赋给套接字s的本地地址,其长度可变,结构随通信域的不同而不同。
第三个参数表示第二个参数的长度
如果没有发生错误,bind()返回0,否则返回SOCKET_ERROR
地址在建立套结字通信过程中起着重要作用,作为一个网络应用程序设计者对套接字地址结构必须有明确认识,
TCP/IP协议的地址结构为:
struct sockaddr_in{
short sin_family; /*AF_INET*/
u_short sin_port; /*16位端口号,网络字节顺序*/
struct in_addr sin_addr; /*32位IP地址,网络字节顺序*/
char sin_zero[8]; /*保留*/
};
sin_family表示地址族,对于IP地址,sin_family成员将一直是AF_INET
sin_port指定的是将要分配给套接字的端口
sin_addr给出的是套接字的主机IP地址
sin_zero只是一个填充数,以使sockaddr_in结构和sockaddr结构的长度一样
如果这个函数调用成功,它将返回0。如果调用失败,这个函数就会返回一个SOCKET_ERROR,错误信息可以通过WSAGetLastError函数返回。
建立套结字连接-------connect()与accept()
Connect()用于建立连接,无连接的套接字进程也可以调用connect,但这时在进程之间没有实际的报文交换,调用将从本地操作系统直接返回。
Connect:
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
第一个参数是欲建立连接的本地套接字描述符
第二个参数说明对方套接字地址结构的指针
第三个参数说明对方套接字的长度
调用成功返回0.失败返回SOCKET_ERROR
在面向连接的协议中,该调用导致本地系统与外部系统之间连接实际建立
accept()系统调用
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
accept面向连接服务器,后面两个参数存放客户端的地址信息,调用前,参数addr指向一个初始值为空的地址结构,addrlen 的初始值为0,调用后,服务器从编号为sockfd的套接字上接受客户连接请求,而连接请求是客户端的connect()调用发出的,当有连接请求到达时,accept()调用将请求连接队列上的第一个客户端套接字地址及其长度放入addr和addrlen并创建一个与sockfd有相同特性的新的套接字号,新的套接字可用于 处理服务器并发请求。
监听连接------listen()
此系统调用面向服务器,表示它愿意接收连接
Listen()要在accept()之前调用
int listen(int sockfd, int backlog);
第一个参数表示本地已经建立,尚未连接的套接字号,服务器愿意从上面接收请求
第二个参数表示请求连接队列的最大长度,用于限制监听队列请求的个数,目前允许的最大值为5,
调用成功返回0,调用失败:SOCK_ERROR
在执行调用时可为没有调用bind()的套接字完成所必须的连接,并建立长度为第二个参数的请求队列
Socket()
bind()
Listen()
accept()
数据传输:
send() recv()/ sendfrom recvfrom
当一个连接建立以后,就可以传输数据了:
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
第一个参数为已连接的本地套接字描述符,
第二个参数buf 是指向存有发送数据的缓冲区的指针
第三个参数长度指定缓冲区的长度
第四个指定传输方式:如是否发送带外数据
调用成功返回总共发送的字节数,否则返回SOCKET_ERROR
Recv()函数调用:
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
第一个参数:已经连接的套结字描述符
第二个参数:指向接收输入数据缓冲区的指针
第三个参数:接收数据的长度
第四个参数:指定控制方式:如是否接收带外数据
调用成功:返回接收的总字节数
连接被关闭:返回0
否则:返回SOCKET_ERROR
Socket()指定五元组中的协议元,它的用法与是否为客户端或者服务器,是否面向连接无关。
bind()指定五元组中的本地二元:本地的主机地址和端口号,它的用法与面向连接有关
在服务器方,无论是否面向连接,均要调用bind()
在客户端方,若采用面向连接,可以不调用bind(),通过connect自动完成,若采用无连接,
客户端必须时用bind()以获取一个唯一的地址
这些仅仅是对于客户端/服务器模式而言,实际上套结字的使用是非常灵活的。
后面我还会再写关于socket的知识,这是第一篇~~~~~
- Socket的基础知识(一)
- socket 的基础知识(一)
- Socket基础知识(一)
- SOCKET基础知识(一)
- iOS中的Socket编程,Socket基础知识(一)
- Socket编程的基础知识
- socket的基础知识
- HTML的基础知识(一)
- mybatis的基础知识 (一)
- PHP的基础知识(一)
- nodeJs的基础知识(一)
- WEB代码的一些基础知识(一)
- 锋利的JQuery----JavaScript基础知识(一)
- 剑指offer:面试的基础知识(一)
- C#基础知识的整理(一)
- java面试用到的基础知识(一)
- Linux基础知识的学习(一)
- JavaScript基础知识(一、二的补充)
- Kotlin学习笔记(一)安装
- IMX6之Openwrt移植增加u-boot支持
- 两数之和
- 比较ArrayList、LinkedList、Vector
- [SDOI2016] BZOJ4602 齿轮-dfs-带权并查集-数论逆元-质因数分解
- socket 的基础知识(一)
- 谷歌浏览器安装json插件
- in thread "main" ImportError: Cannot import site module and its dependencies: No module named site
- imx6之openwrt 3G无线上网卡拨号--以华为EC189为例
- WebView图片上传
- spring AOP理解
- Spring Data Jpa --分页、排序查询
- 【百度】有趣的排序
- PyCharm两种安装Markdown插件的方法