首页 > 编程笔记 > 操作系统笔记

套接字是什么,套接字通信及其原理

套接字(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 提供三种不同类型的套接字:
  1. 面向连接的 TCP 套接字是用 Socket 类实现的;
  2. 无连接的 UDP 套接字使用 DatagramSocket 类。
  3. 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 这样实际的主机名。

使用套接字的通信,虽然常用和高效,但是属于分布式进程之间的一种低级形式的通信。原因是套接字只允许在通信线程之间交换无结构的字节流。客户机或服务器程序需要自己加上数据结构

所有教程

优秀文章