java.net.Socket 解析

Socket构造

  1. public Socket()
    构造一个Socket,因为没有指定目标主机和端口,所以不会通过网络进行连接。

  2. public Socket(Proxy proxy)
    通过一个代理构建一个未连接的Socket。

  3. public Socket(String host, int port)
    通过一个主机和端口构建一个Socket。构造Socket的时候会连接目标主机,如果连接不到目标主机则会抛出IOException或UnknownHostException异常。

  4. public Socket(InetAddress address, int port)
    通过一个InetAddress 和端口构建一个Socket,构造的时候也会进行连接目标主机,同3。

  5. public Socket(String host, int port, InetAddress localAddr, int localPort)
    通过一个要连接的远程主机和端口,并指定从本地哪个ip和端口连接。

  6. public Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
    通过一个要连接的远程主机和端口,并指定从本地哪个ip和端口连接。同5。

获取Socket相关的信息

获取远程主机相关信息

public SocketAddress getRemoteSocketAddress()
public InetAddress getInetAddress()
public int getPort()

获取本地相关信息

public SocketAddress getLocalSocketAddress()
public InetAddress getLocalAddress()
public int getLocalPort()

上面6个方法获取本地和远程主机端口相关的信息。如果socket未连接则返回null,如果socket已经关闭则返回已经连接过的本地和远程主机端口的信息。

connect方法

public void connect(SocketAddress endpoint) 
public void connect(SocketAddress endpoint, int timeout)

connet放提供了两个方法,一个是传入一个SocketAddress 进行连接目标地址
另一个是通过一个SocketAddress 和超时等待时间来连接目标地址。

代码示例:

Socket socket = new Socket();
SocketAddress socketAddr = new InetSocketAddress("www.baidu.com", 80);
socket.connect(socketAddr);
//socket.connect(socketAddr, 2000);

代码中使用了Socket的空构造函数进行构造Socket对象。空构造不会进行连接目标主机(因为没有设置目标地址),需要使用connet方法进行连接目标主机。

代理服务器

//构造代理服务器地址
SocketAddress sa = new InetSocketAddress("192.168.10.130", 808);
//构造Socket代理
Proxy proxy = new Proxy(Proxy.Type.SOCKS, sa);
//使用代理创建socket
Socket socket = new Socket(proxy);
//构造目标地址
SocketAddress socketAddr = new InetSocketAddress("www.baidu.com", 80);
//socket使用代理连接目标地址
socket.connect(socketAddr);

使用public Socket(Proxy proxy)构造方法来构造一个使用proxy的socket。
以后使用该socket的相关的网络操作都会通过代理服务器进行连接。

读取、写入数据

使用下面两个放进行向远程主机读取数据和写入数据进行交互。

public InputStream getInputStream()
public OutputStream getOutputStream()

通过这两个方法我们可以发现,使用socket进行交换操作,其实就是对流的操作。

下面是使用getInputStream和getOutputStream方法对远程主机进行交换的示例。

Socket socket = new Socket("127.0.0.1", 9000);
OutputStream os = socket.getOutputStream();
//通过OutputStream流向远程服务器写如数据
...
InputStream is = socket.getInputStream();
//通过InputStream流读取响应的数据。
...

半关闭连接

如果想关闭socket的输入或输出则可以使用一下两个方法。

public void shutdownInput()
public void shutdownOutput()

当调用shutdownInput()时,则不允许再次从socket中读取数据。
当调用shutdownOutPut()方法后会告诉流已经输入完成,不允许再次输入。对方读取流时,会接受到流结束标志(会返回-1)。

但关闭输入或输出是不会关闭socket的,因为他们不会释放本地端口,还需要调用socket的close()方法来关闭socket。

下面两个方法来判断socket的输入或输出流是否关闭。

public boolean isInputShutdown()
public boolean isOutputShutdown()

如果socket未连接(通过空构造方法构造的socket),也会返回false(未关闭状态)。

判断socket是否关闭

//是否连接过目标地址
public boolean isConnected()
//是否关闭过socket
public boolean isClosed()

isConnected方法并不是连接状态才返回true,而是只要连接过目标地址就返回true,哪怕已经关闭的socket也会返回true的。
isClosed方法是判断socket是否调用close()方法关闭过socket。
如果使用空构造方法构建socket而不连接目标主机,还没调用close方法,该方法会返回true。

所以要判断该socket是否连接目标地址需要这样判断

//打开过连接,但还没有关闭连接
if(socket.isConnected() && !socket.isClosed()){
     System.out.println("连接状态");
}else{
     System.out.println("未打开连接或已经关闭连接");
}

设置Socket选项

java中只支持9个选项。下面简单描述下

  1. TCP_NODELAY
    不使用tcp缓冲区,来多少个字节就发送多少个字节。而不用等缓存区达到多少个字节再发送。
public void setTcpNoDelay(boolean on)
public boolean getTcpNoDelay()
  1. SO_REUSEADDR
    当socket关闭后,程序不会立刻释放端口,而是等一段时间才释放。如果这时当前socket只是为了重启而无法立刻绑定到该端口上,此时使用该选项就可以立刻绑定到该端口上。
public void setReuseAddress(boolean on)
public boolean getReuseAddress()
InetAddress addr = InetAddress.getByName("192.168.31.186");
System.out.println(addr.getHostAddress());
Socket socket = new Socket("www.baidu.com",80,addr,9999);
//关闭后不会马上是否端口
socket.close();
//如果
socket.setReuseAddress(false);
socket = new Socket("www.baidu.com",80,addr,9000);
socket.close();
  1. SO_TIMEOUT
public synchronized int getSoTimeout()
  1. SO_LINGER
public int getSoLinger()
  1. SO_SNDBUF
  1. SO_RCVBUF
  1. SO_KEEPALIVE
public void setKeepAlive(boolean on)
  1. OOBINLINE
  1. IP_TOSS

想了解更多精彩内容请关注我的公众号

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容