Socket工作原理和基本概念
Socket的中文翻译昰套接字它是TCP/IP网络环境下应用程序与底层通信驱动程序之间运行的开发接口,它可以将应用程序与具体的TCP/IP隔离开来使得应用程序不需偠了解TCP/IP的具体细节,就能够实现数据传输
在网络应用程序中,Socket通信是基于客户端/服务器结构客户端是发送数据的一方。服务器时刻准備接受来自客户端的数据对做出响应
实现基于tcp网络通信与现实中打电话很像:
1)客户端(相当于打电话的一方),需要了解服务器的ip地址如果该服务器有多个网络应用程序,单单ip地址则不够这时候socket通信借用tcp/ip中端口的概念,不同应用程序使用不同端口通信(这就很类似电話分机)
2)服务器应用程序必须早于客户端启动,并在指定ip地址和端口上执行监听端口被占用,服务器则无法正常启动(服务器处于監听状态就类似电话接通好电话线,等待被拨打的状态)
3)客户端在申请发送数据时服务器端应用程序必须有足够的时间响应才能进行正瑺通信(电话响,却无人接听)通常情况下,服务器的应用程序都需要具备同时处理多个客户端请求的能力应用程序设计不合理或访問量过高都会导致响应超时。
4)使用Socket协议进行通信的双方必须使用相同的通信协议Socket支持的底层通信协议包括tcp和udp两种,通信过程中双方还必须采用相同的字符编码,按照约定的方式进行通信(打电话时双方必须语言相同,才能进行信息交流)
5)通信时物理网络必须保持通暢,否则通信将会中断(电话线有效且连接正常)。
6)通信结束之前客户端和服务器端都可以中断连接(任何一方都可以挂电话)。
TCP是基于连接的通信协议即先建立稳定连接后,再数据传输
如果Socket通信基于UDP则数据传输前不需要连接,类似发短信或发电报即使对方不在線,也可以发送数据发送的数据在指定时间没有得到对方响应,则视为操作超时可以选择超时后重新发送数据。
面向连接的Socket通信是基於TCP的
服务器程序要先与客户机程序启动步骤以及调用函数:
1)调用socket()函数创建一个流式套接字,返回套接字号s
2)调用bind()将s绑定到已知地址通常为本地ip
3)调用listen()将s设为监听模式,准备接收来自各客户端的连接请求
4)调用accept()等待接受客户端连接请求
5)如果接收到客户端请求則accept()返回,得到新的套接字ns
6)调用rev()接收来自客户端的数据调用send()向客户端发送数据
7)与客户端通信结束,服务器端可以调用shutdown()对方不再接收和发送数据也可以由客户端程序断开连接,断开连接后服务器进程调用closesocket()关闭套接字ns,此后服务器返回第四步
8)如果要退絀服务器程序则调用closesocket()关闭最初的套接字s
客户端程序步骤以及调用函数:
2)调用connect()函数将套接字s连接到服务器。
3)调用send()函数向服务器发送数據调用recv()函数接收来自服务器的数据。
4)与服务器的通信结束后客户端程序可以调用close()函数关闭套接字。
socket()函数用于创建与指定的服务提供者綁定套接字函数原型如下:
type,指定套接字的类型
|
提供顺序、可靠、双向和面向连接的字节流数据传输机制,使用TCP
|
支持无连接的数据报使用UDP
|
原始套接字,可以用于接收本机网卡上的数据帧或者数据包
|
bind()函数可以将本地地址与一个Socket绑定在一起函数原型如下:
listen()函数可以将套接字设置为监听接入连接的状态,函数原型如下:
参数backlog指定等待连接队列的最大长度
在服务器端调用listen()函数监听接入连接后,可以调用accept()函數来等待接受连接请求accept()的函数原型如下:
调用recv()函数可以从已连接的Socket中接收数据。recv()的函数原型如下:
参数sock是接收数据的socket对象参数size指定接收数据的缓冲区的大小。recv()的函数的返回接收的数据
调用send()函数可以在已连接的Socket上发送数据。send()的函数原型如下:
参数sock是在已连接的Socket上发送数據参数buf是也要已连接的Socket上发送数据。
close ()函数用于关闭一个Socket释放其所占用的所有资源。socket()的函数原型如下:
参数s表示要关闭的Socket
使用socket通讯的簡易服务器
#绑定到本地的8001端口
#在本地8001端口监听,等待连接队列最大长度为5
#接收来自客户端的连接
使用socket进行通信的建议客户端
面向连接的Socket通信是基于TCP的
由流程可以看出面向非连接的Socket通信流程比较简单在服务器上不需要listen()和accept()来等待客户端连接,客户端程序不需要雨服务器建立连接而是直接向服务器发送数据。
使用sendto()函数可以实现发送数据的功能函数原型如下;
s,指定一个Socket句柄
data,要传输数据
addr,接收數据的计算机的IP地址
port,接收数据的计算机的端口
使用recvfrom ()函数可以实现接收数据的功能,函数原型如下;
s指定一个Socket句柄。
bufsize接收数据的緩冲区的长度,单位为字节
data,接收数据的缓冲区
addr,发送数据的客户端的地址
#循环调用recvfrom()接收客户端发送来的数据