客户端Socket
导语
java.net.Socket类是JAVA完成客户端TCP操作的基础类。其他建立TCP网络连接的类(如URL,URLConnection和EditorPane)最终会调用这个类的方法。这个类本身使用原生代码与主机操作系统的本地TCP栈进行通信
基本构造函数
每个Socket构造函数指定要连接的主机和端口。主机可以指定InetAddress或主机名,端口可以指定1到65535之间的int值。
pubic Socket(String host, int port)
public Sokcet(InetAddress host, int port)
示例代码
public static void main(String[] args) {
try {
InetAddress inet = InetAddress.getByName("www.xdysite.cn");
Socket toMy = new Socket(inet, 80);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
在示例代码中创建一个Socket连接到www.xdysite.cn主机
构造但不连接
目前为止我们讨论的所有构造函数在创建Socket对象时会打开一个与远程主机的网络连接。如果想要分解创建对象与连接这两个操作,可以不为Socket提供任何参数。在将来的某个时刻再提供主机地址和端口。
public static void main(String[] args) {
try (Socket socket = new Socket()){
SocketAddress sa = new InetSocketAddress("www.xdysite.cn", 80);
//配置Socket连接
socket.setSoTimeout(15000);
//连接服务器
socket.connect(sa);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
上面的代码中只有调用了connect方法后采取连接目标机
连接超时处理
connet方法还有一个参数来指定连接超时时间。connect(SocketAddress endpoint, int timeout)方法中的第二个参数如果为0的话将会无限等待下去,直到连接成功。否则指定一个大于0的参数来设置超时时间。在使用Socket的的有参构造器时都会调用connet方法并timeout设置为0,这点在编程时需要注意。
使用代理服务器
一般情况下,Socket使用的代理服务器可以由socksProxyHost和socksProxyPort系统属性来控制,这些属性应用于系统中所有的Socket。但是如果我们需要使用别的代理的话,也可以用 Socket()来指定。下面就是一个简单的示例代码。
SocketAddress proxyAddress = new InetSocketAddress("myproxy.example.cn", 1080);
Proxy proxy = new Proxy(Proxy.Type.SOCKS, proxyAddress);
Socket s = new Socket(proxy);
SocketAddress remote = new InetSocketAddress("www.xdysite.cn", 9000);
try {
s.connect(remote);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
设置Socket选项
JAVA中的Socket选项依赖于操作系统的Socket选项,因为JAVA中的Socket最终还是要调用操作系统中的API。下面是客户端Sokcet可以设置的一些选项。
- TCP_NODELAY
- SO_BINDADDR
- SO_TIMEOUT
- SO_LINGER
- SO_SNDBUF
- SO_RCVBUF
- SO_KEEPALIVE
- OOBINLINE
- IP_TOS
这些名字来自于UNIX系统所使用的C头文件中的命名常量,因为Socket来自于UNIX操作系统。下面对这几个常量进行说明。
TCP_NODELAY
设置TCP_NODELAY为true时可确保包尽可能快的发送(不进行缓冲,一有数据就发)。正常情况下,为了提高吞吐量,小数据包(比如一字节)在发送前会组合为更大的包。在发送另一个包之前,本地主机要等待远程系统对前一个包的确认。这种算法被称为Nagle算法。这种算法在某些情况下存在严重的问题。比如远程桌面系统。服务器要实时扑住客户端鼠标移动的操作。如果使用缓冲在加上网速很慢的话,那么最后的效果就很差强人意了。
public void setTcpNoDelay(boolean on)
通过上面的方法来设置该参数的值,如果底层Socket不支持TCP_NODELAY选项,则会抛出异常
SO_TIMEOUT
正常情况下,调用read()方法从Socket 读取数据时都会阻塞,直到有数据时才返回。设置SO_TIMEOUT可以确保阻塞的时间不会超过某个固定的毫秒数。当时间到期时就会抛出一个InterruptedIOException异常。不过,即使超时了,Socket仍是连接的,所以可以再次调用read()去读数据。
SO_LINGER
public void setSoLinger(boolean on, int seconds)
选项SO_LINGER指定了Socket关闭时如何处理尚未发送的数据报。默认情况下,close()方法将立即返回,但系统仍会尝试发送剩余的数据。如果通过设置函数将其设置为false(第二个参数将不起作用),那么当 Socket关闭的时候,所有未发送的数据包都将被丢弃。如果将其设置为true,并指定一个时间,那么 close()方法将会阻塞(阻塞的时间为指定的秒数)。如果时间一到, Socket将会关闭,所有剩余的数据将不会发送,也不会接受数据。
SO_KEEPALIVE
如果打开SO_KEEPALIVE,客户端偶尔会通过一个空闲的连接发送一个数据包(一般是两小时一次),以确保服务器未崩溃。如果服务器没有响应这个包,客户端会在将来的11分钟内持续尝,直到接收到响应为止。如果在12分钟内未收到响应,客户端就会关闭socket。SO _KEEPALIVE默认值是false,这表明客户端不会检查服务器是否挂掉。
public void setKeepAlive(boolean on)
Socket异常
Socket类的大多数方法都声明抛出IOException或其子类java.net.SocketException。不过,仅仅知道发生了问题,这对于处理问题往往是不够的。是不是因为远程主机忙而拒绝连接?还是因为没有服务在这个端口上监听而导致远程主机拒绝连接?或者是因为网络拥塞或主机崩溃而导致连接超时?SocketException有几个子类。可以对出现的问题以及为什么出现问题提供有关的信息:
public class BindException extends SocketException
public class ConnectException extends SocketException
public class NoRouteToHostException extends SocketException
如果试图在一个正在使用的端口上构造Socket或ServerSocket对象,或者你没有足够的权限使用这个端口,就会抛出BindException异常。当连接被远程主机拒绝,而拒绝的原因通常是由于主机忙或者是没有进程监听这个端口,此时就会抛出ConnectionException异常。最后一点, NoRouteToHostException异常是因为连接已过期。
一个简单的示例
通过这个示例,我们练习一下客户端编程。whois服务器的功能是进行域名的查询,下面是通过telnet的方式来查询一个域名的信息。
我们通过telnet连接到whois服务器,查询了域名为xdysite.cn的信息。下面我们通过java来实现这一查询功能。
public static void main(String[] args) {
try (Socket socket = new Socket("ewhois.cnnic.cn", 43)) {
Writer writer = new OutputStreamWriter(socket.getOutputStream());
writer.write("xdysite.cn\n");
writer.flush();
Reader reader = new InputStreamReader(socket.getInputStream(), "utf-8");
int c = 0;
while ((c = reader.read()) != -1) {
System.out.print((char)c);
}
writer.close();
reader.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
客户端Socket的更多相关文章
- 服务器中判断客户端socket断开连接的方法
1, 如果服务端的Socket比客户端的Socket先关闭,会导致客户端出现TIME_WAIT状态,占用系统资源. 所以,必须等客户端先关闭Socket后,服务器端再关闭Socket才能避免TIME_ ...
- socket系列之客户端socket——Socket类
假设TCP套接字服务器端已经建立好并正在监听客户端的连接了,那么客户端就可以通过Socket类来发起连接.客户端发起一个连接请求后,就被动地在等待服务器的响应.这个类同样位于java.net包中,包含 ...
- tcp客户端socket
import socket # 和udp的区别显而易见,udp发送和接收的是一个元祖,因为udp是不建立连接的,只有得到了对方的端口和ip才能进行沟通. # 而tcp不是,tcp发送和接受的是一个字符 ...
- 服务器中判断客户端socket断开连接的方法【转】
本文转载自:http://www.cnblogs.com/jacklikedogs/p/3976208.html 1, 如果服务端的Socket比客户端的Socket先关闭,会导致客户端出现TIME_ ...
- 常量,字段,构造方法 调试 ms 源代码 一个C#二维码图片识别的Demo 近期ASP.NET问题汇总及对应的解决办法 c# chart控件柱状图,改变柱子宽度 使用C#创建Windows服务 C#服务端判断客户端socket是否已断开的方法 线程 线程池 Task .NET 单元测试的利剑——模拟框架Moq
常量,字段,构造方法 常量 1.什么是常量 常量是值从不变化的符号,在编译之前值就必须确定.编译后,常量值会保存到程序集元数据中.所以,常量必须是编译器识别的基元类型的常量,如:Boolean ...
- java多线程实现多客户端socket通信
一.服务端 package com.czhappy.hello.socket; import java.io.IOException; import java.net.InetAddress; imp ...
- java 网络编程基础 TCP/IP协议:服务端ServerSocket;客户端Socket; 采用多线程方式处理网络请求
1.Java中客户端和服务器端通信的简单实例 Java中能接收其他通信实体连接请求的类是ServerSocket,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一 ...
- Java Springboot webSocket简单实现,调接口推送消息到客户端socket
Java Springboot webSocket简单实现,调接口推送消息到客户端socket 后台一般作为webSocket服务器,前台作为client.真实场景可能是后台程序在运行时(满足一定条件 ...
- linux 客户端 Socket 非阻塞connect编程
开发测试环境:虚拟机CentOS,windows网络调试助手 非阻塞模式有3种用途 1.三次握手同时做其他的处理.connect要花一个往返时间完成,从几毫秒的局域网到几百 ...
随机推荐
- 纯C#的ini格式配置文件读写
虽然C#里都是添加app.config 并且访问也很方便 ,有时候还是不习惯用他.那么我们来做个仿C++下的那种ini配置文件读写吧,其他人写的都是调用非托管kernel32.dll.我也用过 但是感 ...
- jQuery 中bind(),live(),delegate(),on() 区别(转)
当我们试图绑定一些事件到DOM元素上的时候,我相信上面这4个方法是最常用的.而它们之间到底有什么不同呢?在什么场合下用什么方法是最有效的呢? 准备知识: 当我们在开始的时候,有些知识是必须具备的: D ...
- 仿QQ空间根据位置弹出PopupWindow显示更多操作效果
我们打开QQ空间的时候有个箭头按钮点击之后弹出PopupWindow会根据位置的变化显示在箭头的上方还是下方,比普通的PopupWindow弹在屏幕中间显示好看的多. 先看QQ空间效果图: ...
- jquery弹出可关闭遮罩提示框
jquery CSS3遮罩弹出层动画效果,使用非常简单,就两个标签,里面自定义内容和样式,四种常见效果,懂的朋友还可以修改源代码修改成自己想要的效果 效果展示 http://hovertree.com ...
- 深入理解javascript选择器API系列第二篇——getElementsByClassName
× 目录 [1]使用 [2]classList [3]扩展 前面的话 既然有getElementById()和getElementsByTagName()方法,为什么没有getElementsByCl ...
- Spark中Lambda表达式的变量作用域
通常,我们希望能够在lambda表达式的闭合方法或类中访问其他的变量,例如: package java8test; public class T1 { public static void main( ...
- HTML学习(二)进阶篇
在博客园中有许多大神对HTML超文本标记语言写了很多内容,总结了很多知识,这里对我看到的博客文章, 所学到的知识,做一个总结. 一)列表和表格 dl→definition list(定义列表),见备 ...
- Linux下的SVN服务器搭建
Linux下的SVN服务器搭建 鉴于在搭建时,参考网上很多资料,网上资料在有用的同时,也坑了很多人 本文的目的,也就是想让后继之人在搭建svn服务器时不再犯错,不再被网上漫天的坑爹作品所坑害,故此总 ...
- 原创 C++应用程序在Windows下的编译、链接:第一部分 概述
本文是对C++应用程序在Windows下的编译.链接的深入理解和分析,文章的目录如下: 我们先看第一章概述部分. 1概述 1.1编译工具简介 cl.exe是windows平台下的编译器,link.ex ...
- 从MySQL 5.5迁移到Mariadb 10.1.14
从MySQL 5.5迁移到Mariadb 10.1.14 迁移计划如下: 1.备份MySQL 5.5的数据库,对指定库进行备份. 2.还原到Mariadb,然后建立复制. 3.然后就可以愿意啥时候切换 ...