关闭

Java网络编程由浅入深二 Socket的构造和连接服务端的相关异常

标签: socketjava网络编程
785人阅读 评论(0) 收藏 举报
分类:

Socket构造方法和Socket的设置与异常

本文将介绍Socket的构造方法和Socket的相关属性设置与异常处理

  • 构造Socket
  • 设置等待超时时间
  • 设置服务器地址
  • 设置客户端地址
  • 客户端连接服务器可能出现的异常

构造Socket

Socket的构造方法有如下几种重载方式:

Socket();
Socket(InetAddress address, int port)
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
Socket(Proxy proxy)
Socket(SocketImpl impl)
Socket(String host, int port)
Socket(String host, int port, InetAddress localAddr, int localPort)

除了第一个构造器外,其他构造器都会尝试与服务器建立连接,如果连接成功返回Socket对象;如果因为某些原因连接失败,就抛出IOException。
如下代码扫描主机上从1到1024之间的端口,判断这些端口是否已经被服务器程序监听。

public class PortScanner {
    public static void main(String[] args) {
        String host = "localhost";
        new PortScanner().scan(host);
    }

    public void scan(String host){
        Socket socket = null;
        for(int i=0;i<1024;i++){
            try {
                socket = new Socket(host, i);
                System.out.println("There is a server on port "+i);
            }  catch (IOException e) {
                System.out.println("Can't connect to port "+i);
            }finally{
                if(socket!=null){
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

设置等待建立连接的超时时间

使用不带参数的构造方法,设置socket连接超时时间:

Socket socket = new Socket();
SocketAddress endPoint = new InetSocketAddress("localhost", 8000);
socket.connect(endPoint, 60000);

以上代码表示用于连接本机上监听的8000端口,等待连接的最长时间为1分钟。如果在1分钟内连接成功,则connect()方法顺利返回;如果在1分钟之内出现异常,则抛出异常;如果超过1分钟,既没有连接成功,也没有抛出异常,那么会抛出SocketTimeoutExceptionsocket. connect(SocketAddress endpoint, int timeout);负责连接服务器,参数endpoint指定服务器地址,参数timeout设定超时时间,以毫秒为单位。如果参数timeout为0,表示永远不超时。

设置服务器地址

Socket的构造方法中,除了第一个不带参数的构造方法,其他构造方法都需要指定服务器地址,包括服务器的IP或主机名,以及端口:
Socket(InetAddress address, int port)
Socket(String host, int port)
InetAddress类表示服务器的IP地址,InetAddress提供了很多静态方法:

    // 返回本地主机的IP地址
    InetAddress.getLocalHost();
    // 返回代表10.202.164.65的IP地址
    InetAddress.getByName("10.202.164.65");
    // 返回域名为'www.csdn.net'的ip地址
    InetAddress.getByName("www.csdn.net");

设置客户端的地址:

默认情况下,客户端的IP地址来自于客户端程序所在的主机,客户端的端口则由操作系统随机分配。但是Socket类还是提供了构造方法允许显式地设置客户端的IP和端口:

//参数localAddr和localPort用来设置客户端的IP和端口。
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
Socket(String host, int port, InetAddress localAddr, int localPort)

客户端连接服务器可能抛出的异常

当Socket构造方法请求连接服务器时,可能会抛出下面的异常:
• UnknownHostException:如果无法识别主机的名字或IP地址,就会抛出这种异常

• ConnectException:如果没有服务器进程监听指定的端口,或者服务器拒绝连接,就会抛出这种异常。

• SocketTimeoutException:如果等待连接超时,就会抛出这种异常。

• BindException:如果无法把Socket对象与指定的本地IP地址或端口绑定,就会抛出这种异常。

通过下面测试类为例,演示抛出异常的原因。

public class ConnectTester {
    public static void main(String[] args) {
        String host = "www.csdn.net";
        int port = 12312;

        new ConnectTester().connect(host, port);
    }

    public void connect(String host,int port){
        SocketAddress remoteAddress = new InetSocketAddress(host, port);
        Socket socket = null;
        String result = null;
        try{
            socket = new Socket();
            long start = System.currentTimeMillis();
            socket.connect(remoteAddress,1000);
            long end = System.currentTimeMillis();
            result = (end-start)+"ms";
        }catch(BindException bindException){
            result = "BindException,Socket对象与指定的本地IP地址或端口绑定,异常";
        }catch (UnknownHostException unknownHostException) {
            result = "UnknownHostException,无法识别的主机";
        }catch (ConnectException connectException) {
            result = "ConnectException,连接被拒绝";
        }catch (SocketTimeoutException socketTimeoutException) {
            result = "SocketTimeoutException,连接超时";
        }catch(IOException e){
            result = "IOException,连接失败";
        }finally{
            if(socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println(remoteAddress+" : "+result);
    }
}

• 抛出UnknownHostException情况:
如果无法识别主机的名字或IP地址,就会抛出这种异常。例如:host为:’ somehost11’。Socket的connect方法就会抛出UnknownHostException异常。
• 抛出ConnectException的情况:
在以下两种情况会抛出ConnectException。
1) 没有服务器进程监听指定的端口。例如:host为 ‘localhost’ port为 12321 。如果本机的12321端口没有被任何进程监听,则Socket连接方法会抛出ConnectException。
2) 服务器进程拒绝连接。介绍服务器进程拒绝客户的连接请求的情形。如下示例代码,一个简单的服务程序ServerSocket构造方法中的第二个参数表示请求队列的长度。如果队列的请求已满,服务器就会拒绝其余的请求。抛出ConnectException

public class SimplServer {
    public static void main(String[] args) throws Exception{
        ServerSocket serverSocket = new ServerSocket(8888, 2);
        Thread.sleep(3600000);
    }
}
public class SimpleClient {
    public static void main(String[] args) throws Exception{
        String host = "localhost";
        int port = 8888;
        Socket s1 = new Socket(host, port);
        System.out.println("第一次连接成功");
        Socket s2 = new Socket(host, port);
        System.out.println("第二次连接成功");
        Socket s3 = new Socket(host, port);
        System.out.println("第三次连接成功");
    }
}

• 抛出SocketTimeoutException的情形
如果客户端连接超时,就会抛出这种异常。修改 socket.connect(remoteAddress, 1);由原来的1000毫秒修改为1毫秒,这样增加了超时的可能性。

• 抛出BindException的情形:
将代码

socket = new Socket();
socket.connect(remoteAddress, 1000);

修改为:

socket = new Socket();
socket.bind(new InetSocketAddress(InetAddress.getByName("222.34.5.6"), 5678));
socket.connect(remoteAddress, 1000);

修改后的代码试图把Socket的本地IP地址设为222.34.5.6,把本地端口设置为5678。如果本机不具有该IP,或者端口被占用,那么就会出现BindException。


欢迎关注微信公众号 在路上的coder 每天分享优秀的Java技术文章!
扫描二维码关注:这里写图片描述

1
0
查看评论

socket简介

<br />Java中的网络编程是一个很重要的部分,也是其编程优越性的地方之一。在Java中有一个专门的Java.net类库来管理网络编程的有关方法。   <br />  下面先介绍在Java中怎样用socket进行客户与服务器通信。最后再介绍一个一个最简...
  • fjymine2
  • fjymine2
  • 2011-03-14 20:33
  • 340

关于Socket链接服务器可能产生的异常

import java.io.IOException; import java.net.BindException; import java.net.ConnectException; import java.net.InetSocketAddress; import java.net.Socket...
  • wuxinliulei
  • wuxinliulei
  • 2014-04-07 13:19
  • 1949

socket网络编程(2):socket操作相关函数

1、setsockopt()可以用来设置接收、发送超时 int TimeOut=30000;//设置接收超时30秒 if(setsockopt(m_SocketClientCommand,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeO...
  • milanleon
  • milanleon
  • 2014-07-19 10:48
  • 1038

网络编程(22)—— socket客户端和服务端收发数据包需要一对一的关系吗?

其实这个题目应该是一个疑问句,接触了这么久的TCPIP网络编程,一直不敢确定是不是在客户端和服务端分别进行读和写时,write和read要成对出现? 我想这也是很多网络编程的新手存在的疑问吧。         下面,就针对这个问题进行试验,以解答长久以来的疑惑...
  • lzhui1987
  • lzhui1987
  • 2016-10-25 14:03
  • 1214

java网络编程实现客户端连接服务器端,并发送消息例子(1)。(阻塞式的方法)

昨天晚上学了网络线程,并写了一个,客户端连接服务器的简单例子,有点QQ的感觉,但是实际上还差远,差不多就是很久之前那种“长江长江我是黄河”的通话形式。 代码如下: 服务器端代码:import java.io.IOException; import java.io.InputStream; imp...
  • u012036171
  • u012036171
  • 2015-06-27 11:06
  • 1727

网络编程,要不要区分客户端和服务端

网络编程,要不要区分客户端和服务端 一个程序是作为客户端还是服务器,决定了它在与其对等端(peer) 建立通信时使用的套接字API的形式(客户端的对等端是服务器,反之亦然)。更进一步来说,客户端与服务器端的区别非常重要, 因为客户端首先需要知道服务器的地址和端口号,反之则不需要。如果有必要,服...
  • KuaiLeShiFu
  • KuaiLeShiFu
  • 2016-12-29 18:31
  • 718

Java高级编程-网络编程详解 (3)

Datagram(数据报)是一种尽力而为的传送数据的方式,它只是把数据的目的地记录在数据包中,然后就直接放在网络上,系统不保证数据是否能安全送到,或者什么时候可以送到,也就是说它并不保证传送质量。     1 UDP套接字   &...
  • lifeng_2009
  • lifeng_2009
  • 2010-04-07 17:31
  • 1091

Socket的java网络编程原理

一,网络编程中两个主要的问题一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输。在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可以唯一地确定Internet上的一台主机。而TCP层则提供面向应用的可靠的或非可靠的数据传输机制,这是网...
  • Siobhan
  • Siobhan
  • 2009-06-17 19:16
  • 7017

java Socket 一个服务器与多个客户端进行通信

在实现一个服务器与多个客户端进行通信的时候,此时就需要引入多线程编程,用多个线程同时为多个客户提供服务,这时提高服务器你并发性能最长用的手段,服务器的主线程负责接收客户的连接,每次接收到一个客户连接就会创建一个工作线程,由它负责与客户通信。 多线程的服务器代码实现: public cl...
  • WannerWang
  • WannerWang
  • 2015-10-15 17:50
  • 1043

网络编程知识(2)--Socket理解

本文转载自:http://www.cnblogs.com/dolphinX/p/3460545.html 尊重原创TCP/IP要想理解socket首先得熟悉一下TCP/IP协议族, TCP/IP(Transmission Control Protocol/Internet Protocol)即传输...
  • Mrzhoug
  • Mrzhoug
  • 2016-05-09 17:02
  • 761
    欢迎关注个人微信号
      欢迎关注微信账号:在路上的coder .每天一篇java相关或互联网相关的文章




    个人资料
    • 访问:826201次
    • 积分:2957
    • 等级:
    • 排名:第14104名
    • 原创:87篇
    • 转载:4篇
    • 译文:0篇
    • 评论:26条
    资源分享地址
    个人博客地址
    博客专栏
    最新评论