Socket编程

来源:互联网 发布:多因子选股 知乎 编辑:程序博客网 时间:2024/06/08 16:09

本文主要内容参考自此处,如有兴趣可自行查看(英文版),这里是本人对于该部分内容的理解和总结。

1. 关于Socket通信

Q1: socket是什么,该怎么理解?
A1:这里引用JLS定义

java.net.Socket

This class implements client sockets (also called just “sockets”). A socket is an endpoint for communication between two machines.

一句话表示:一个socket是两个机器之间建立连接的一个端点。
个人理解:想要在2个节点之间建立通信,其中一个节点的角色是client,另一个节点的角色是server。
1).则首先服务端开启服务,new ServerSocekt(int port),服务器创建一个绑定在port端口的服务器,并可以调用函数serverSocket.accept()等待客户端连接,该函数可以阻塞给定时间(通过serverSocket.setSoTimeOut(int time))。
2).然后在客户端尝试建立连接 new Socket(String hostname, int port), 创建一个连接在hostname服务器的port端口的socket。这里并没有指定客户端socket的本地端口,可以通过socket.getLocalSocketAddress()查看本地socket的IP地址和端口号,通过运行结果可知,每次通信的端口号是变化的–是系统分配的。
3)在建立连接之后,就可以使用: 输入输出流操作进行数据的传输了。

DataOutputStream dos = new DataOutputStream(socket.getOutputStream());dos.writeUTF(String str);DataInputStream dis = new DataInputStream(socket.getInputStream());dis.readUTF(void);

Q2: socket通信所使用的协议是什么?

我们可用于socket编程的共有2种协议,分别是datagram通讯(datagram communication)和流式通讯(stream communication)。
Datagram Communication(数据报通信):Datagram communication protocol, UDP, 是一种无连接的服务,这意味着每次发送datagram时也必须发送本地的socket描述符和接受者的socket描述符。也就是说每次建立通讯时必须发送附加信息。
Stream communication(流式通信):所谓的流式通信协议就是著名的TCP(transfer control protocol), 不同于UDP,TCP是一种面向连接的协议,为了在TCP协议上实现通信,必须首先在一对socket之间建立连接。其中之一监听连接请求(server),另一个请求连接(client)。一旦两个sockets建立连接之后,可以在sockets之间进行双向数据传输。

2. 使用TCP通信的Socket代码实现(含服务端和客户端)

请按顺序运行服务端和客户端程序,如果在运行时抛出异常,请检查所使用端口是否可用(0~1023是为系统预留的端口号,所以测试时选择大于1023的端口号);检查防火墙释放开启(本人在Mac OSX 10.12.6上测试时抛出异常问题是通过关闭Setting中的Firewall解决的)。

服务端代码:

// package com.fqyuan.socket_test;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class Server {    public static void main(String[] args) throws IOException {        ServerSocket serverSocket = new ServerSocket(2000);        serverSocket.setSoTimeout(10000);        while (true) {            System.out.println("Server waiting to be connected...");            try {                Socket server = serverSocket.accept();                InputStream is = server.getInputStream();                DataInputStream dis = new DataInputStream(is);                System.out.println(dis.readUTF());                OutputStream os = server.getOutputStream();                DataOutputStream dos = new DataOutputStream(os);                dos.writeUTF("Hello world from server: "+server.getLocalSocketAddress()+" GoodBye!");                server.close();            } catch (Exception e) {                System.out.println("Timeout!");                break;            }        }    }}

客户端代码:

// package com.fqyuan.socket_test;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;import java.net.UnknownHostException;public class Client {    public static void main(String[] args) {        try{        Socket client = new Socket("localhost", 2000);        System.out.println("Trying to connect to " + client.getRemoteSocketAddress());        OutputStream os = client.getOutputStream();        DataOutputStream dos = new DataOutputStream(os);        dos.writeUTF("Msg from client " + client.getLocalSocketAddress());        InputStream is = client.getInputStream();        DataInputStream dis = new DataInputStream(is);        System.out.println(dis.readUTF());        client.close();    }catch(Exception e){        e.printStackTrace();    }    }}

运行结果:
这里写图片描述

3. 一般流程

1). 打开一个socket;
2). 打开该socket对应的datainputstream和dataoutputstream;
3). 根据服务端的协议向socket中读写数据;
4). 最后的清理工作(包括数据的处理和socket的关闭等)。

原创粉丝点击