二. Socket用法

C/S通信架构中,客户端要主动与服务端建立连接,这个链接就是Socket套接字.服务端收到连接请求后,也会开启Socket记录与客户端的链接.C/S两端都要建路Socket才能正常收发数据.

一.构造Socket

(1)new Socket ( )
(2)new Socket ( InetAddress addres,int port )
(3)new Socket ( String hostnamme,int port )
以上3种创建socket的构造函数,除第一种外,都要试图简历与服务器的连接,连接成功返回Socket对象,连接失败,抛出IOException

/** 扫描主机1-1024之间的端口,判断这些端口上是否有程序进行监听
     *  PortScanner与1-1024端口建立Socket对象,建立成功说明该端口上有程序进行监听
     */
    public class PortScanner {
        public static void main(String[] args) {
            Socket socket = null;
            for (int i = 1; i < 1024; i++) {
                try {
                    socket = new Socket("localhost",i);
                    System.out.println(i+"端口有程序在监听");
                } catch (IOException e) {
                    System.out.println(i+"端口空闲");
                }finally {
                    try {
                        if(socket!=null)
                            socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }   
                }   
            }   
        }   
    }

二. 建立连接超时时间的Socket

    默认情况下,与服务端链接建立Socket时,会一直阻塞,直到服务端的操作系统返回信息表示连接建立,或抛出异常表示该端口无应用程序响应.受网络影响,Socket返回会有很长等待时间,因此可以设置建立连接产生Socket的阻塞时间(超时时间)

Socket socket = new Socket();
socket.connect(new InetSocketAddress("localhost",8080),60*1000); //一分钟超时时间

三. Socket信息

getInetASddress();     // 获取与之连接的服务端ip
getPort();             // 获取与之连接的服务端port
getLocalAddress();     
getLocalPort();        // 客户端为该进程开启的端口

四. Socket关闭

当客户端与服务端通信结束,客户端应及时关闭Socket,释放为其开启的端口标识和其他资源

finally {    // 释放操作放在finally块中
    try {
        if(socket!=null)
            socket.close();
    } catch (IOException e) {
        e.printStackTrace();
}

Socket可以只关闭输入流或者输出流

shutdownInput();
shutdownOutput();

五. Socket选项

1. TCP_NODELAY
    Socket连接发送数据默认采用Negale算法,即发送方发送的数据先缓存在底层缓冲区,当缓冲区满后,再将数据发送出去.这种方法减少了数据的传输次数来提高通信效率,适合发送大量数据,且接收方会及时相应的场景下.
    若发送方连续发送小批量数据,这些数据不会立刻发送而是会先缓存起来,导致实时响应速度很慢;例如客户端鼠标移动的信息需要实时发送到服务器上,采用Negale算法,会大大降低实时响应速度.
    关闭Negale发送算法 : setTcpNoDelay();
2. SO_RESUSEADDR:
    socket的close()方法触发后,操作系统不会立刻释放该Socket所占端口,而是等一段时间,确保收到网络上发来的延迟数据,并不对该数据做任何处理.该段时间过后才释放端口.防止被其他恰巧绑定到相同端口的新进程收到该延迟数据.
    客户端来讲,操作系统为进程随机开启端口,一般不会使得新进程绑定到老进程的端口.对于服务端来说,进程挂掉后立即重启会重启失败,因为底层端口未被释放,而服务端进程应该响应客户端发来的延迟数据,所以服务端进程可以设置端口重用(setResuseAddress(true)).只有新老进程都设置了SO_RESUSEADDR,才能立刻端口重用

//SO_RESUSEADDR要在Socket未绑定本地port钱调用,否则该选项设置无效,用如下方式开启socket链接
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket();
        socket.setReuseAddress(true);
        socket.connect(new InetSocketAddress("localhost",8080),60*1000); //一分钟超时时间
    }

3. SO_TIEMOUT

byte[] buff = new byte[1024];
InputStream in = socket.getInputStream();
in.read(buff);

若没有数据可读,则会一直阻塞,setTimeout(60*1000),设置读阻塞的超时时间为1分钟
4. SO_LINGER
Socket的close方法会立即返回,但底层端口未被立即释放,会延迟一段时间,等到所有数据发送,且接收到所有返回的确认包后,才真正关闭.socket的setSoLinger(true,3600),设置close()方法自多阻塞3600秒,若还有数据未被发送,则丢弃该部分数据
5. SO_KEEPALIVE
默认情况,Socket的KEEPALIVE选项为false,客户端发完消息,如果不手动调用close(),则socket会一直存在,不释放资源.setKeepAlive(true)后,当通信两端没有数据传输时,操作系统发现该socket已超过2小时空闲,则会自动发送一个测试包给远程机器,测试包会持续尝试11分钟,若在12分钟内没收到远程机器发来的确认包,操作系统则会自动关闭本地Socket,释放资源
6. OOBINLINE
当setOOBLine(true),操作系统支持发送紧急数据,sendUrgent(int data)发送一个字节的紧急数据.默认情况OOBINLINE为false.但是接收方仍会把改紧急数据放到普通数据的队列中,紧急数据到来,接收方不会得到任何通知,所以接收方无法区分普通数据和紧急数据,只能按照相同方式处理

转载于:https://www.cnblogs.com/72808ljup/p/5290085.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java.net.Socket 是 Java 语言中用于实现网络通信的类,它提供了一种在网络上进行数据传输的机制,可以用于构建客户端和服务器端应用程序。 要使用 Java.net.Socket 类,通常需要遵循以下步骤: 1. 创建一个 Socket 对象。在创建 Socket 对象时需要指定要连接的服务器地址和端口号。 2. 使用 Socket 对象建立连接。在连接建立之前,Socket 对象会尝试连接指定的服务器地址和端口号。如果连接建立成功,Socket 对象会返回一个输入流和一个输出流,可以用于在客户端和服务器端之间传输数据。 3. 使用输入流和输出流进行数据传输。在建立连接后,可以使用输入流和输出流进行数据传输。可以使用输入流从服务器端读取数据,也可以使用输出流向服务器端发送数据。 4. 关闭 Socket 连接。在数据传输完成后,需要关闭 Socket 连接以释放资源。可以使用 Socket 对象的 close() 方法来关闭连接。 下面是一个简单的示例,演示如何使用 Java.net.Socket 类来连接一个服务器,并向服务器发送数据: ```java import java.net.*; import java.io.*; public class SocketExample { public static void main(String[] args) throws IOException { String serverName = "localhost"; int port = 8080; try { System.out.println("Connecting to " + serverName + " on port " + port); Socket client = new Socket(serverName, port); System.out.println("Just connected to " + client.getRemoteSocketAddress()); OutputStream outToServer = client.getOutputStream(); DataOutputStream out = new DataOutputStream(outToServer); out.writeUTF("Hello from " + client.getLocalSocketAddress()); InputStream inFromServer = client.getInputStream(); DataInputStream in = new DataInputStream(inFromServer); System.out.println("Server says " + in.readUTF()); client.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` 在上面的示例中,我们首先创建了一个 Socket 对象,并指定要连接的服务器地址和端口号。然后,我们使用 Socket 对象的 getOutputStream() 方法获取一个输出流,并使用 DataOutputStream 对象向服务器发送一条消息。接下来,我们使用 Socket 对象的 getInputStream() 方法获取一个输入流,并使用 DataInputStream 对象从服务器接收一条消息。最后,我们使用 Socket 对象的 close() 方法关闭连接。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值