Java 套接字(Socket)

    |     2015年3月29日   |   Java网络编程   |     0 条评论   |    1348

在客户机/服务器(C/S)模式里,Server 端要同时接待多台 Client。除了用 IP 标识一台机器,还要用端口号标识后台正在服务的线程。IP 加上端口,就是网络套接字(Socket)。

Java 里服务端用 ServerSocket,客户端用 Socket。端口 0~1023 留给系统(例如 HTTP 用 80、Telnet 用 23),1024~65535 给应用程序。

一、两类 Socket 与两种通信方式

Server 在若干端口上同时提供不同服务;Client 接入某一个端口,请 Server 为自己干活。双方通信可以想象成打电话:Client 先拨号,Server 监听,接通之后谁都可以说话。

方式 协议 特点
流式 Socket TCP 有连接:先连后传,结束再拆;正确、可靠
数据报 Socket UDP 无连接:分包直接发,快,但不保证可靠

流式 Socket 在两端之间建一条通道,可读可写。会话过程固定四步:建立连接 → 拿到输入/输出流 → 读/写 → 关闭套接字。

二、客户端与服务端怎么建连接

客户端用 Socket(String host, int port),host 是主机名或 IP(不要写成带 http:// 的网址),port 是事先约定的端口:

try {
    Socket mySocket = new Socket("www.warmtel.com", 1860);
} catch (IOException e) {}

然后用 getInputStream() 读对端放入「线路」的数据,用 getOutputStream() 往线路里写。

服务端用 ServerSocket(int port),端口必须和客户端呼叫的端口一致:

try {
    ServerSocket serverSocket = new ServerSocket(1860);
} catch (IOException e) {}

监听端口上一旦有 Client 请求,就用 accept() 得到一个 Socket,再和对方通信。撤销服务时关闭这个 Socket:

try {
    Socket sc = serverSocket.accept(); // sc 是一个 Socket 对象
} catch (IOException e) {}
sc.close();

三、例 13-3:Client 端

Client 向本机 4441 端口请求连接,连上后向服务器写一句,再读回服务器的回复。注意 DataInputStream.readUTF() 读完不会返回 null,对端关闭时会抛 EOFException,所以这里改成读一次就结束,避免空指针判断失效。

import java.io.*;
import java.net.*;
public class Client {
    public static void main(String args[]) {
        String s = null;
        Socket mySocket;
        DataInputStream in = null;
        DataOutputStream out = null;
        try {
            mySocket = new Socket("localhost", 4441);
            in = new DataInputStream(mySocket.getInputStream());
            out = new DataOutputStream(mySocket.getOutputStream());
            out.writeUTF("good server!");
            s = in.readUTF();
            System.out.println(s);
            mySocket.close();
        } catch (IOException e) {
            System.out.println("can't connect");
        }
    }
}

四、例 13-4:对应的 Server 端

程序在 4441 端口监听。收到客户请求后,读入客户发来的字符串,再回一句「客户,你好,我是服务器」。原文把这段标成「例 10.3」,应对齐上面的例 13-3。

import java.io.*;
import java.net.*;
public class Server {
    public static void main(String args[]) {
        ServerSocket server = null;
        Socket you = null;
        String s = null;
        DataOutputStream out = null;
        DataInputStream in = null;
        try {
            server = new ServerSocket(4441);
        } catch (IOException e1) {
            System.out.println("ERROR:" + e1);
        }
        try {
            you = server.accept();
            in = new DataInputStream(you.getInputStream());
            out = new DataOutputStream(you.getOutputStream());
            s = in.readUTF();
            out.writeUTF("客户,你好,我是服务器");
            out.close();
        } catch (IOException e) {
            System.out.println("ERROR:" + e);
        }
    }
}

为了发挥并行能力,可以把套接字通信交给独立线程:客户端发起请求、或服务器接到一个客户时,启动专门线程去创建流、完成双方交流。这样主线程可以继续 accept() 下一个连接。

一句话总结:Socket = IP + 端口;客户端 Socket 拨号、服务端 ServerSocket.accept() 接听,流式 TCP 可靠、数据报 UDP 更快但不保证到达。

转载请注明来源:Java 套接字(Socket)
本文链接地址:https://ai.zhousir.top/?p=28
回复 取消