Java编程那些事儿103——网络编程技能2
副标题#e#
13.2.3 TCP编程
凭据前面的先容,网络通讯的方法有TCP和UDP两种,个中TCP方法的网络通讯是指在通讯的进程中保持毗连,有点雷同于打电话,只需要拨打一次号码(成立一次网络毗连),就可以多次通话(多次传输数据)。这样方法在实际的网络编程中,由于传输靠得住,雷同于打电话,假如甲给乙打电话,乙说没有听清楚让甲反复一遍,直到乙听清楚为止,实际的网络传输也是这样,假如发送的一方发送的数据吸收方以为有问题,则网络底层会自动要求发送方重发,直到吸收方收到为止。
在Java语言中,对付TCP方法的网络编程提供了精采的支持,在实际实现时,以java.net.Socket类代表客户端毗连,以java.net.ServerSocket类代表处事器端毗连。在举办网络编程时,底层网络通讯的细节已经实现了较量高的封装,所以在措施员实际编程时,只需要指定IP地点和端标语码就可以成立毗连了。正是由于这种高度的封装,一方面简化了Java语言网络编程的难度,别的也使得利用Java语言举办网络编程时无法深入到网络的底层,所以利用Java语言举办网络底层系统编程很坚苦,详细点说,Java语言无法实现底层的网络嗅探以及得到IP包布局等信息。可是由于Java语言的网络编程较量简朴,所以照旧得到了遍及的利用。
在利用TCP方法举办网络编程时,需要凭据前面先容的网络编程的步调举办,下面别离先容一下在Java语言中客户端和处事器端的实现步调。
在客户端网络编程中,首先需要成立毗连,在Java API中以java.net.Socket类的工具代表网络毗连,所以成立客户端网络毗连,也就是建设Socket范例的工具,该工具代表网络毗连,示譬喻下:
Socket socket1 = new Socket(“192.168.1.103”,10000);
Socket socket2 = new Socket(“www.sohu.com”,80);
上面的代码中,socket1实现的是毗连到IP地点是192.168.1.103的计较机的10000号端口,而socket2实现的是毗连到域名是www.sohu.com的计较机的80号端口,至于底层网络如何实现成立毗连,对付措施员来说是完全透明的。假如成立毗连时,本机网络不通,或处事器端措施未开启,则会抛出异常。
毗连一旦成立,则完成了客户端编程的第一步,紧接着的步调就是凭据“请求-响应”模子举办网络数据互换,在Java语言中,数据传输成果由Java IO实现,也就是说只需要从毗连中得到输入流和输出流即可,然后将需要发送的数据写入毗连工具的输出流中,在发送完成今后从输入流中读取数据即可。示例代码如下:
OutputStream os = socket1.getOutputStream(); //得到输出流
InputStream is = socket1.getInputStream(); //得到输入流
上面的代码中,别离从socket1这个毗连工具得到了输出流和输入流工具,在整个网络编程中,后续的数据互换就酿成了IO操纵,也就是遵循“请求-响应”模子的划定,先向输出流中写入数据,这些数据会被系统发送出去,然后在从输入流中读取处事器端的反馈信息,这样就完成了一次数据互换进程,虽然这个数据互换进程可以多次举办。
这里得到的只是最根基的输出流和输入流工具,还可以按照前面进修到的IO常识,利用流的嵌套将这些获获得的根基流工具转换成需要的装饰流工具,从而利便数据的操纵。
最后当数据互换完成今后,封锁网络毗连,释放网络毗连占用的系统端口和内存等资源,完成网络操纵,示例代码如下:
socket1.close();
#p#副标题#e#
这就是最根基的网络编程成果先容。下面是一个简朴的网络客户端措施示例,该措施的浸染是向处事器端发送一个字符串“Hello”,并将处事器端的反馈显示到节制台,数据互换只举办一次,当数据互换举办完成今后封锁网络毗连,措施竣事。实现的代码如下:
package tcp;
import java.io.*;
import java.net.*;
/**
* 简朴的Socket客户端
* 成果为:发送字符串“Hello”随处事器端,并打印出处事器端的反馈
*/
public class SimpleSocketClient {
public static void main(String[] args) {
Socket socket = null;
InputStream is = null;
OutputStream os = null;
//处事器端IP地点
String serverIP = "127.0.0.1";
//处事器端端标语
int port = 10000;
//发送内容
String data = "Hello";
try {
//成立毗连
socket = new Socket(serverIP,port);
//发送数据
os = socket.getOutputStream();
os.write(data.getBytes());
//吸收数据
is = socket.getInputStream();
byte[] b = new byte[1024];
int n = is.read(b);
//输出反馈数据
System.out.println("处事器反馈:" + new String(b,0,n));
} catch (Exception e) {
e.printStackTrace(); //打印异常信息
}finally{
try {
//封锁流和毗连
is.close();
os.close();
socket.close();
} catch (Exception e2) {}
}
}
}
#p#分页标题#e#
在该示例代码中成立了一个毗连到IP地点为127.0.0.1,端标语码为10000的TCP范例的网络毗连,然后得到毗连的输出流工具,将需要发送的字符串“Hello”转换为byte数组写入到输出流中,由系统自动完成将输出流中的数据发送出去,假如需要强制发送,可以挪用输出流工具中的flush要领实现。在数据发送出去今后,从毗连工具的输入流中读取处事器端的反馈信息,读取时可以利用IO中的各类读取要领举办读取,这里利用最简朴的要领举办读取,从输入流中读取到的内容就是处事器端的反馈,并将读取到的内容在客户端的节制台举办输出,最后依次封锁打开的流工具和网络毗连工具。
这是一个简朴的成果示例,在该示例中演示了TCP范例的网络客户端根基要领的利用,该代码只起演示目标,还无法到达实用的级别。
假如需要在节制台下面编译和运行该代码,需要首先在节制台下切换到源代码地址的目次,然后依次输入编译和运行呼吁:
javac -d . SimpleSocketClient.java
java tcp.SimpleSocketClient
和下面将要先容的SimpleSocketServer处事器端组合运行时,措施的输出功效为:
处事器反馈:Hello
先容完一个简朴的客户端编程的示例,下面接着先容一下TCP范例的处事器端的编写。首先需要说明的是,客户端的步和谐处事器端的编写步调差异,所以在进修处事器端编程时留意不要和客户端夹杂起来。
在处事器端措施编程中,由于处事器端实现的是被动期待毗连,所以处事器端编程的第一个步调是监听端口,也就是监听是否有客户端毗连达到。实现处事器端监听的代码为:
ServerSocket ss = new ServerSocket(10000);
该代码实现的成果是监听当前计较机的10000号端口,假如在执行该代码时,10000号端口已经被此外措施占用,那么将抛出异常。不然将实现监听。
处事器端编程的第二个步调是得到毗连。该步调的浸染是当有客户端毗连达到时,成立一个和客户端毗连对应的Socket毗连工具,从而释放客户端毗连对付处事器端端口的占用。实现成果就像公司的前台一样,当一个客户达到公司时,会汇报前台我找某某某,然后前台就通知某某某,然后就可以继承欢迎其它客户了。通过得到毗连,使得客户端的毗连在处事器端得到了保持,别的使得处事器端的端口释放出来,可以继承期待其它的客户端毗连。实现得到毗连的代码是:
Socket socket = ss.accept();
该代码实现的成果是获恰当前毗连随处事器端的客户端毗连。需要说明的是accept和前面IO部门先容的read要领一样,都是一个阻塞要领,也就是当无毗连时,该要领将阻塞措施的执行,直到毗连达到时才执行该行代码。别的获获得的毗连将利用处事器端其它未利用的端标语和客户端举办毗连,使得处事器端端口不会被一直占用。由于每个得到的毗连城市占用处事器端的一个端标语,这样利用TCP范例的网络举办编程时,同时可以支持的最大毗连数量受到端口数量的限制,最大为65535个。
毗连得到今后,后续的编程就和客户端的网络编程雷同了,这里得到的Socket范例的毗连就和客户端的网络毗连一样了,只是处事器端需要首先读取发送过来的数据,然后举办逻辑处理惩罚今后再发送给客户端,也就是互换数据的顺序和客户端互换数据的步调恰好相反。这部门的内容和客户端很雷同,所以就不反复了,假如还不熟悉,可以参看下面的示例代码。
最后,在处事器端通信完成今后,封锁处事器端毗连。实现的代码为:
ss.close();
这就是根基的TCP范例的处事器端编程步调。下面以一个简朴的echo处事实现为例子,先容综合利用示例。echo的意思就是“反映”,echo处事器端实现的成果就是将客户端发送的内容再原封不动的反馈给客户端。实现的代码如下:
#p#分页标题#e#
package tcp;
import java.io.*;
import java.net.*;
/**
* echo处事器
* 成果:将客户端发送的内容反馈给客户端
*/
public class SimpleSocketServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
OutputStream os = null;
InputStream is = null;
//监听端标语
int port = 10000;
try {
//成立毗连
serverSocket = new ServerSocket(port);
//得到毗连
socket = serverSocket.accept();
//吸收客户端发送内容
is = socket.getInputStream();
byte[] b = new byte[1024];
int n = is.read(b);
//输出
System.out.println("客户端发送内容为:" + new String(b,0,n));
//向客户端发送反馈内容
os = socket.getOutputStream();
os.write(b, 0, n);
} catch (Exception e) {
e.printStackTrace();
}finally{
try{
//封锁流和毗连
os.close();
is.close();
socket.close();
serverSocket.close();
}catch(Exception e){}
}
}
}
在该示例代码中成立了一个监听当前计较机10000号端口的处事器端Socket毗连,然后得到客户端发送过来的毗连,假如有毗连达到时,读取毗连中发送过来的内容,并将发送的内容在节制台举办输出,输出完成今后将客户端发送的内容再反馈给客户端。最后封锁流和毗连工具,竣事措施。
在节制台下面编译和运行该措施的呼吁和客户端部门的雷同。
这样,就以一个很简朴的示例演示了TCP范例的网络编程在Java语言中的根基实现,这个示例只是演示了网络编程的根基步调以及各个成果要领的根基利用,只是为网络编程打下了一个基本,下面迁就几个问题来深入先容网络编程深条理的一些常识。