套接字是什么,套接字通信及其原理
套接字(socket)为通信的端点,每个套接字由一个 IP 地址和一个端口号组成。通过网络通信的每对进程需要使用一对套接字,即每个进程各有一个。
通常,套接字采用客户机-服务器架构。服务器通过监听指定端口,来等待客户请求。服务器在收到请求后,接受来自客户套接字的连接,从而完成连接。
实现特定服务(如 telnet、ftp 和 http)的服务器监听众所周知的端口(telnet 服务器监听端口 23,ftp 服务器监听端口 21,Web 或 http 服务器监听端口 80)。所有低于 1024 的端口都是众所周知的,我们可以用它们来实现标准服务。
当客户进程发出连接请求时,它的主机为它分配一个端口。这个端口为大于1024的某个数字。例如,当 IP 地址为 146.86.5.20 的主机 X 的客户希望与 IP 地址为 161.25.19.8 的 Web 服务器(监听端口 80)建立连接时,它所分配的端口可为1625。该连接由一对套接字组成:主机 X 上的(146.86.5.20:1625), Web服务器上的(161.25.19.8:80)。这种情况如图 1 所示。根据目的端口号码,主机之间传输的分组可以发送到适当的进程。
图 1 采用套接字的通信
所有连接必须是唯一的。因此,当主机 X 的另一个进程希望与同样的 Web 服务器建立另一个连接时,它会分配到另一个大于 1024 但不等于 1625 的端口号。这确保了所有连接都由唯一的一对套接字组成。
为了演示套接字,本节我们会用 Java 语言,因为 Java 提供一个更加简单的套接字接口而且提供丰富的网络工具库。
Java 提供三种不同类型的套接字:
下面的例子,即日期服务器,采用面向连接的 TCP 套接字。这个操作允许客户机向服务器请求当前的日期和时间。服务器监听端口 6013,当然端口号可以是任何大于 1024 的数字。在接收到连接时,服务器将日期和时间返回给客户机。
服务器如何与套接字通信的有关细节如下。服务器首先建立 PrintWriter 对象,以便与客户进行通信。PrintWriter 对象允许服务器通过输出方法 print() 和 printin() 写到套接字。服务器通过方法 println() 发送日期到客户机。服务器在将日期写到套接字后,就关闭与客户相连的套接字,并且重新监听更多请求。
为与服务器通信,客户创建一个套接字,并且连到服务器监听的端口。以下的 Java 程序为客户机的实现。
IP 地址 127.0.0.1 为特殊 IP 地址,称为回送。当计算机采用地址 127.0.0.1 时,它引用自己。这一机制允许同一主机的客户机和服务器可以通过 TCP/IP 协议进行通信。IP 地址 127.0.0.1 可以换成运行日期服务器的另一主机的 IP 地址。除 IP 地址外,也可采用如
使用套接字的通信,虽然常用和高效,但是属于分布式进程之间的一种低级形式的通信。原因是套接字只允许在通信线程之间交换无结构的字节流。客户机或服务器程序需要自己加上数据结构。
通常,套接字采用客户机-服务器架构。服务器通过监听指定端口,来等待客户请求。服务器在收到请求后,接受来自客户套接字的连接,从而完成连接。
实现特定服务(如 telnet、ftp 和 http)的服务器监听众所周知的端口(telnet 服务器监听端口 23,ftp 服务器监听端口 21,Web 或 http 服务器监听端口 80)。所有低于 1024 的端口都是众所周知的,我们可以用它们来实现标准服务。
当客户进程发出连接请求时,它的主机为它分配一个端口。这个端口为大于1024的某个数字。例如,当 IP 地址为 146.86.5.20 的主机 X 的客户希望与 IP 地址为 161.25.19.8 的 Web 服务器(监听端口 80)建立连接时,它所分配的端口可为1625。该连接由一对套接字组成:主机 X 上的(146.86.5.20:1625), Web服务器上的(161.25.19.8:80)。这种情况如图 1 所示。根据目的端口号码,主机之间传输的分组可以发送到适当的进程。
图 1 采用套接字的通信
所有连接必须是唯一的。因此,当主机 X 的另一个进程希望与同样的 Web 服务器建立另一个连接时,它会分配到另一个大于 1024 但不等于 1625 的端口号。这确保了所有连接都由唯一的一对套接字组成。
为了演示套接字,本节我们会用 Java 语言,因为 Java 提供一个更加简单的套接字接口而且提供丰富的网络工具库。
Java 提供三种不同类型的套接字:
- 面向连接的 TCP 套接字是用 Socket 类实现的;
- 无连接的 UDP 套接字使用 DatagramSocket 类。
- MulticastSocket 类为 DatagramSocket 类的子类,多播套接字允许数据发送到多个接收者。
下面的例子,即日期服务器,采用面向连接的 TCP 套接字。这个操作允许客户机向服务器请求当前的日期和时间。服务器监听端口 6013,当然端口号可以是任何大于 1024 的数字。在接收到连接时,服务器将日期和时间返回给客户机。
import java.net.*; import java.io.*; public class DateServer { public static void main(String[] args) { try { ServerSocket sock = new ServerSocket(6013); /* now listen for connections */ while (true) { Socket client = sock.accept(); PrintWriter pout = new PrintWriter(client.getOutputStream(),true); /* write the Date to the socket */ pout. println (new java.util.Date().toString()); /* close the socket and resume */ /* listening for connections */ client.close(); } } catch (IOException ioe) { System.err.println(ioe); } } }此程序为日期服务器程序。服务器创建一个 ServerSocket,监听端口号 6013,然后调用 accept() 方法,开始监听端口。服务器阻塞在方法 accept() 上,等待客户请求连接。当接收到连接请求时,accept() 返回一个套接字,以供服务器与客户进程进行通信。
服务器如何与套接字通信的有关细节如下。服务器首先建立 PrintWriter 对象,以便与客户进行通信。PrintWriter 对象允许服务器通过输出方法 print() 和 printin() 写到套接字。服务器通过方法 println() 发送日期到客户机。服务器在将日期写到套接字后,就关闭与客户相连的套接字,并且重新监听更多请求。
为与服务器通信,客户创建一个套接字,并且连到服务器监听的端口。以下的 Java 程序为客户机的实现。
import java.net.*; import java.io.*; public class DateClient { public static void main(String[] args) { try { /* make connection to server socket */ Socket sock = new Socket("127.0.0.1",6013); InputStream in = sock.getInputStreamO ; BufferedReader bin = new BufferedReader(new InputStreamReader(in)); /* read the date from the socket */ String line; while ( (line = bin.readLine()) != null) System.out.printIn(line); /* close the socket connection*/ sock.close() ; } catch (IOException ioe) { System.err.printIn(ioe); } } }客户创建一个 Socket,并与 IP 地址为 127.0.0.1 的服务器端口 6013 建立连接。连接建立后,客户就通过普通的流 I/O 语句来从套接字进行读取。在收到服务器的日期后,客户就关闭端口,并退出。
IP 地址 127.0.0.1 为特殊 IP 地址,称为回送。当计算机采用地址 127.0.0.1 时,它引用自己。这一机制允许同一主机的客户机和服务器可以通过 TCP/IP 协议进行通信。IP 地址 127.0.0.1 可以换成运行日期服务器的另一主机的 IP 地址。除 IP 地址外,也可采用如
www.westminstercollege.edu
这样实际的主机名。使用套接字的通信,虽然常用和高效,但是属于分布式进程之间的一种低级形式的通信。原因是套接字只允许在通信线程之间交换无结构的字节流。客户机或服务器程序需要自己加上数据结构。
所有教程
- socket
- Python基础教程
- C#教程
- MySQL函数
- MySQL
- C语言入门
- C语言专题
- C语言编译器
- C语言编程实例
- GCC编译器
- 数据结构
- C语言项目案例
- C++教程
- OpenCV
- Qt教程
- Unity 3D教程
- UE4
- STL
- Redis
- Android教程
- JavaScript
- PHP
- Mybatis
- Spring Cloud
- Maven
- vi命令
- Spring Boot
- Spring MVC
- Hibernate
- Linux
- Linux命令
- Shell脚本
- Java教程
- 设计模式
- Spring
- Servlet
- Struts2
- Java Swing
- JSP教程
- CSS教程
- TensorFlow
- 区块链
- Go语言教程
- Docker
- 编程笔记
- 资源下载
- 关于我们
- 汇编语言
- 大数据
- 云计算
- VIP视频