Java网络编程之客户端中的Socket

Socket

Socket是两个主机之间的连接,它有下面7种基本操作:

  • 连接到远程主机
  • 发送数据
  • 接受数据
  • 关闭连接
  • 绑定端口
  • 监听输入数据
  • 在绑定的端口上接受远程机器的连接

前面4中操作是客户端和服务端共有的,后面3种只有服务端才需要(定义在ServerSocket类中)。

从Server读取数据

  @Test
    public void readFromTimeServer() throws IOException {
        //不是创建对象,而是建立连接
        try (Socket socket = new Socket("time.nist.gov",13)){
            socket.setSoTimeout(15000);//设置超时时间15s
            InputStream in = socket.getInputStream();
            StringBuilder time = new StringBuilder();
            InputStreamReader reader = new InputStreamReader(in,"ASCII");
            for (int c = reader.read();c!= -1;c=reader.read()){
                time.append((char)c);
            }
            System.out.println(time);
        }
    }

设置超时时间是一个很好的习惯。

写数据到Server

@Test
    public void writeToServer() throws IOException {
        Socket socket = new Socket("dict.org", 2628);
        socket.setSoTimeout(15000);
        OutputStream out = socket.getOutputStream();
        Writer writer = new OutputStreamWriter(out, "UTF-8");
        writer.write("DEFINE eng-lat gold\r\n");
        writer.flush();
    }

构造和连接Socket

基本构造函数

public Socket(String host, int port) throws UnknownHostException, IOException
public Socket(InetAddress host, int port) throws IOException

在构造函数返回之前,一条与远端的网络连接已经被建立完成。
可以利用构造函数的这个特性来检查有效的端口。

String host = "localhost";
        for (int i = 1; i < 1024; i++) {
            try {
                Socket s = new Socket(host, i);
                System.out.println("There is a server on port " + i + " of "
                        + host);
                s.close();
            } catch (UnknownHostException ex) {
                System.err.println(ex);
                break;
            } catch (IOException ex) {
            }
        }

还有3个构造函数创建的是无连接的socket

public Socket()
public Socket(Proxy proxy)
protected Socket(SocketImpl impl)

SocketAddress

SocketAddress代表着连接的终端地址。
SocketAddress可以用来保存IP地址和端口这种信息,可以重用与构造新的Socket。

public SocketAddress getRemoteSocketAddress()
public SocketAddress getLocalSocketAddress()

这两个方法分别用来获取一个连接的远端地址和本地地址。

Socket socket = new Socket("www.yahoo.com", 80);
SocketAddress yahoo = socket.getRemoteSocketAddress();
socket.close();
//Later, you could reconnect to Yahoo! using this address:
Socket socket2 = new Socket();
socket2.connect(yahoo);

获取Socket的相关信息

Socket的下面这几个属性可以通过相应的Get方法获取:
• Remote address
• Remote port
• Local address
• Local port

public InetAddress getInetAddress()
public int getPort()
public InetAddress getLocalAddress()
public int getLocalPort()

但是没有Set方法,因为这些属性会在连接建立成功的时候设置。

getInetAddress()getPort()方法告诉你Socket连接到的远程主机和端口;
getLocalAddress()getLocalPort()方法告诉你Socket连接源端的网卡(network interface)和端口。

与远程端口不同,它通常是“知名端口”,已经由一个标准委员会预先指定;而本地端口通常由系统在运行时从可用的未使用的端口中选择。 这样,同一个系统中多个不同的客户端可以同时访问相同的服务。 本地端口已经和本地主机的IP地址一起嵌入到输出IP数据包,因此服务器可以发送数据到客户端的正确端口。

 String [] args = "www.baidu.com,www.qq.com".split(",");
        for (String host : args) {
            try {
                Socket theSocket = new Socket(host, 80);
                System.out.println("Connected to " + theSocket.getInetAddress()
                        + " on port " + theSocket.getPort() + " from port "
                        + theSocket.getLocalPort() + " of "
                        + theSocket.getLocalAddress());
            } catch (UnknownHostException ex) {
                System.err.println("I can't find " + host);
            } catch (SocketException ex) {
                System.err.println("Could not connect to " + host);
            } catch (IOException ex) {
                System.err.println(ex);
            }
        }

打印:

Connected to www.baidu.com/14.215.177.38 on port 80 from port 32416 of /192.168.5.46
Connected to www.qq.com/59.37.96.63 on port 80 from port 32417 of /192.168.5.46

有个方法叫做isConnected(),它用来判断是否连接过,无法判断现在是否是连接的。如果想判断现在是否是连接状态,可通过下面的代码:

boolean connected = socket.isConnected() && ! socket.isClosed();

Socket中的异常

public class BindException extends SocketException
public class ConnectException extends SocketException
public class NoRouteToHostException extends SocketException

在端口被占用或无访问端口的权限时会抛出BindException;
当客户端尝试连接到远端时,如果远端正忙或者没有监听那个端口,那么会抛出ConnectException;
如果连接超时会抛出NoRouteToHostException;

猜你喜欢

转载自blog.csdn.net/yjw123456/article/details/80706410