查看“核心技术Ⅱ:网络”的源代码
←
核心技术Ⅱ:网络
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:JavaCore]] == 实现服务端 == === 手动实现:telnet === telnet 是一种用于网络编程的调试工具,可以在命令shell中输入telnet来启动它。 * 在Windows中,需要激活telnet:“控制面板”->“程序”->“打开/关闭Windows特性”->“Telnet客户端”。 如: <syntaxhighlight lang="bash"> telnet time-a.nist.gov 13 # 用time-a.nist.gov在端口13上建立telnet会话 </syntaxhighlight> [[File:连接到服务器端口的客户端.png|600px]] === Java实现:socket === <syntaxhighlight lang="java"> import java.io.*; import java.net.*; import java.util.*; public class SocketTest lS { public static void main(String[) args) throwsIOException { try(Socket s = new Socket(”time-a.nist.gov”,13); Scanner in = new Scanner(s.getInputStream(),”UTF-8'’)) { while (in.hasNextline()) { String line = in.nextline(); System.out.println(line); } } } </syntaxhighlight> 如果连接失败,它将抛出一个UnknownHostException异常;如果存在其他问题,它将抛出一个IOException异常。<br/> (<big>[[网络基础]]</big>) ==== 相关方法 ==== jva.net.Socket 1.0 * Socket(String host, int port) *: 构建一个套接字,用来连接给定的主机和端口。 * InputStream getlnputStream() * OutputStream getOutputStream() *: 获取可以从套接字中读取数据的流,以及可以向套接字写出数据的流。 === 套接字超时 === 从套接字读取信息时,在有数据可供访问之前,读操作将会被阻塞。对于不同的应用,应该确定合理的超时值。 # 调用“setSoTimeout”方法设置超时值(单位:毫秒): #: <syntaxhighlight lang="java"> Socket s = new Socket(. . .); s.setSoTimeout(lOOOO); // time out after 10 seconds </syntaxhighlight> # 捕获“SocketTimeoutException”异常: #: 如果已经为套接字设置了超时值,并且之后的读操作和写操作在没有完成之前就超过了时间限制,那么这些操作就会抛出SocketTimeoutException异常; #: <syntaxhighlight lang="java"> try { InputStream in = s.getlnputStream(); //read from in . . . } catch(InterruptedIOException exception) { . . . } </syntaxhighlight> # 使用可以超时的无连接套接字: #* “Socket s = new Socket(String host, int port);”会一直无限期地阻塞下去,直到建立了到达主机的初始连接为止; #: <syntaxhighlight lang="java"> Socket s = new Socket(); s.connect(new InetSocketAddress(host, port), timeout); </syntaxhighlight> ==== 相关方法 ==== jva.net.Socket 1.0 * Socket() 1.1 *: 创建一个还未被连接的套接字。 * void connect(SocketAddress address) 1.4 *: 将该套接字连接到给定的地址。 * void connect(SocketAddress address, int timeoutlnMi11iseconds) 1.4 *: 将套接字连接到给定的地址。如果在给定的时间内没有响应,则返回。 * void setSoTimeout(int timeoutlnMilliseconds) 1.1 *: 设置该套接字上读请求的阻塞时间。如果超出给定时间,则抛出一个InterruptedIOException异常。 * boolean isConnected() 1.4 *: 如果该套接字已被连接,则返回true。 * boolean isClosed() 1.4 *: 如果套接宇已经被关闭,则返回true === 因特网地址 === 如果需要在主机名和因特网地址之间进行转换,那么就可以使用“InetAddress”类: * 只要主机操作系统支持1Pv6格式的因特网地址,java.net包也将支持它; # 静态的“getByName”方法可以返回代表某个主机的InetAddress对象: #: 然后,可以使用“getAddress”方法来访问这些字节; #: <syntaxhighlight lang="java"> InetAddress address = InetAddress.getByName("time-a.nist.gov"); byte[] addressButes = address.getAddress(); </syntaxhighlight> # 调用“getAllByName”方法来获得所有主机: #:(一些访问量较大的主机名通常会对应于多个因特网地址,以实现负载均衡) #: <syntaxhighlight lang="java"> InetAddress[] addresses= InetAddress.getA11ByName(host) ; </syntaxhighlight> # 使用静态的“getlocalHost”方法来得到本地主机的地址: #: <syntaxhighlight lang="java"> InetAddress address = InetAddress.getLocalHost(); </syntaxhighlight> ==== 相关方法 ==== jva.net.InetAddress 1.0 * static InetAddress getByName( String host) * static InetAddress[] getAllByName(String host) *: 为给定的主机名创建一个InetAddress对象,或者一个包含了该主机名所对应的所有因特网地址的数组。 * static InetAddress getlocalHost() *: 为本地主机创建一个InetAddress对象。 * byte[] getAddress() *: 返回一个包含数字型地址的字节数组。 * String getHostAddress() *: 返回一个由十进制数组成的字符串,各数字间用圆点符号隔开,例如,“129.6.15.28”。 * String getHostName() *: 返回主机名。 == 实现服务器 == === 服务器套接字 === # “ServerSocket”类用于建立套接字: #: <syntaxhighlight lang="java"> ServerSocket s = new ServerSocket(8189); </syntaxhighlight> # 建立一个负责监控端口8189的服务器: #: <syntaxhighlight lang="java"> Socket incoming = s.accept(); </syntaxhighlight> # 到输入流和输出流: #: <syntaxhighlight lang="java"> InputStream inStream = incoming.getinputStream(); OutputStream outStream = incoming.getOutputStream(); </syntaxhighlight> # 转换成扫描器和写入器: #: <syntaxhighlight lang="java"> Scanner in= new Scanner(inStream, "UTF-8"); PrintWriterout= new PrintWriter(newOutputStreamWriter(outStream, "UTF-8"), true) ; </syntaxhighlight> # 客户端发送信息: #: <syntaxhighlight lang="java"> out.print1n("Hello! Enter BYE to exit.") </syntaxhighlight> ==== 相关方法 ==== java.net.ServerSocket 1.0 * ServerSocket(int port) *: 创建一个监昕端口的服务器套接字。 * Socket accept() *: 等待连接。该方法阻塞(即,使之空闲)当前线程直到建立连接为止。该方法返回一个Socket对象,程序可以通过这个对象与连接中的客户端进行通信。 * void close() *: 关闭服务器套接字。 === 为多个客户端服务 === 运用线程:每当程序建立一个新的套接字连接,也就是说当调用“accept()”时,启动一个新的线程来处理服务器和该客户端之间的连接,而主程序将立即返回并等待下一个连接。 * 这种方法并不能满足高性能服务器的需求。为使服务器实现更高的吞吐量,可以使用“java.nio”包中一些特性。 <syntaxhighlight lang="java"> package threadad; import java.io.*; import java.net.*; import java.util.*; pub1ic c1ass ThreadedEchoServe { pub1ic static void main (String[] args ) { try(ServerSocket s = new ServerSocket(8189)) { int i = 1; while (true) { Socket incoming = s.accept(); System.out.println("Spawning " + i) ; Runnab1e r = new ThreadedEchoHandler(incoming); Thread t = new Thread(r); t.start(); i++; } } catch(IOException e) { e.printStackTrace(); } } } class ThreadedEchoHandler implements Runnab1e { privete Socket incoming; public ThreadedEchoHandler(Socket incomingSocket) { incoming = incomingSocket; } public void run() { try(InputStream inStream = incoming.getInputStream(); OnputStream onStream = incoming.getOnputStream()) { Scanner in new Scanner(inStream, "UTF-8"); PrintWriter out new PrintWriter( new OutputStreamWriter(outStream, "UTF-8"), true); out.println("Hello! Enter BYE to exit."); } boolean done= false; while(!done && in.hasNextLine()) { String line = in.nextline(); out.println("Echo: "+ line); if (1ine.trim().equals("BYE")) done = true; } catch(IOException e) { e.printStackTrace(); } } } </syntaxhighlight> === 半关闭 === 半关闭(half-close)提供了这样一种能力:套接字连接的一端可以终止其输出,同时仍旧可以接收来自另一端的数据。 客户端使用半关闭方法: <syntaxhighlight lang="java"> try(ServerSocket s = new ServerSocket(host, port)) { Scanner in = new Scanner(socket.getInputStream(), ”UTF-8”); PrintWriter writer = new PrintWriter(socket.getOutputStream()); // send request data Writer.print( . . . ); Writer.flush(); socket.shutdownOutput(); // now socket is ha1f-c1osed // read response data while(in.hasNextLine() != null) { String line = in.nextLine(); . . . } } </syntaxhighlight> 服务器端将读取输入信息,直至到达输入流的结尾,然后它再发送响应。 * 该协议只适用于一站式(one-shot)的服务,例如HTTP服务,在这种服务中,客户端连接服务器,发送一个请求,捕获响应信息,然后断开连接。 ==== 相关方法 ==== java.net.Socket 1.0 * void shutdownOutput() 1.3 *: 将输出流设为“流结束”。 * void shutdownInput() 1.3 *: 将输入流设为“流结束”。 * boo1ean isOutputShutdown() 1.4 *: 如果输出已被关闭,则返回true。 * boo1ean isInputShutdown() 1.4 *: 如果输入已被关闭,则返回true。 == 可中断套接字 == 当连接到一个套接字时,当前线和将会被阻塞且到建立连接或产生超时为止。同样地,当通过套接字读写数据时,当前线程也会被阻塞直到操作成功或产生超时为止。 * 当线程因套接字无法响应而发生阻塞时, 则无法通过调用interrupt来解除阻塞。 为了中断套接字操作,可以使用java.nio包提供的一个特性——“'''SocketChannel'''”类: # 打开SocketChannel: #: 通道(channel)并没有与之相关联的流,它所拥有的read和write方法都是通过使用Buffer对象来实现的(ReadableByteChannel接口和WritableByteChannel接口都声明了这两个方法)。 #: <syntaxhighlight lang="java"> SocketChannel channel = SocketChannel.open(new InetSocketAddress(host, port)); </syntaxhighlight> ## 如果不想处理缓冲区, 可以使用Scanner类从SocketChannel中读取信息: ##: <syntaxhighlight lang="java"> Scanner in = new Scanner(channel, "UTF-8"); </syntaxhighlight> ## 通过调用静态方法“Channels.newOutputStream”可以将通道转换成输出流: ##: <syntaxhighlight lang="java"> OutputStream outStream = Channels.newOutputStream(channel); </syntaxhighlight> ==== 相关方法 ==== java.net.InetSocketAddress 1.4 * InetSocketAddress(String hostname, int port) *: 用给定的主机和端口参数创建一个地址对象,并在创建过程中解析主机名。如果主机名不能被解析,那么该地址对象的unresolved 属性将被设为true。 * boolean isUnresolved() *: 如果不能解析该地址对象, 则返回true。 java.nio.channels.SocketChannel 1.4 * static SocketChannel open(SocketAddress address) *: 打开一个套接字通道,并将其连接到远程地址。 java.nio.channels.Channels 1.4 * static InputStream newinputStream(ReadableByteChannel channel) *: 创建一个输入流,用以从指定的通道读取数据 * static OutputStream newOutputStream(WritableByteChannel channel) *: 创建一个输出流, 用以向指定的通道写入数据 == 获取Web 数 == === URL 和URI === === 使用URLConnection 获取信息 === === 提交表单数据 === == 发送E-mail ==
返回至“
核心技术Ⅱ:网络
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息