java网络通讯编程 html
首先声明一下,刚开始学习java网络通讯编程就对他有一种畏惧感,由于本身对网络一窍不通,因此。。。呵呵。。你懂得,昨天又仔细的学习了一遍,感受其实java网络编程也没想象的那么难,不信,咱一块儿看看。。。呵呵。。java
网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据。程序员所做的事情就是把数据发送到指定的位置,或者接收到指定的数据,这个就是狭义的网络编程范畴。在发送和接收数据时,大部分的程序设计语言都设计了专门的API实现这些功能,程序员只须要调用便可。因此,基础的网络编程能够和打电话同样简单程序员
一:首先看一下网络通信的两种方式编程
1.TCP(传输控制协议)方式数组
TCP方式就相似于拨打电话,使用该种方式进行网络通信时,须要创建专门的虚拟链接,而后进行可靠的数据传输,若是数据发送失败,则客户端会自动重发该数据服务器
2. UDP(用户数据报协议)方式网络
UDP方式就相似于发送短信,使用这种方式进行网络通信时,不须要创建专门的虚拟链接,传输也不是很可靠,若是发送失败则客户端没法得到socket
这两种传输方式都是实际的网络编程中进行使用,重要的数据通常使用TCP方式进行数据传输,而大量的非核心数据则都经过UDP方式进行传递,在一些程序中甚至结合使用这两种方式进行数据的传递。因为TCP须要创建专用的虚拟链接以及确认传输是否正确,因此使用TCP方式的速度稍微慢一些,并且传输时产生的数据量要比UDP稍微大一些。函数
总结一下UDP和TCP协议的区别学习
-使用UDP时,每一个数据报中都给出了完整的地址信息,所以无须要创建发送方和接收方的链接。
–对于TCP协议,因为它是一个面向链接的协议,在socket之间进行数据传输以前必然要创建链接,因此在TCP中多了一个链接创建的时间
–使用UDP传输数据时是有大小限制的,每一个被传输的数据报必须限定在64KB以内。
–TCP没有这方面的限制,一旦链接创建起来,双方的socket就能够按统一的格式传输大量的数据。
–UDP是一个不可靠的协议,发送方所发送的数据报并不必定以相同的次序到达接收方。
–TCP是一个可靠的协议,它确保接收方彻底正确地获取发送方所发送的所有数据
-TCP在网络通讯上有极强的生命力,例如远程链接(Telnet)和文件传输(FTP)都须要不定长度的数据被可靠地传输。
—相比之下UDP操做简单,并且仅须要较少的监护,所以一般用于局域网高可靠性的分散系统中client/server应用程序
二:基于url的网络编程
1.建立一个URL
为了表示URL, java.net中实现了类URL。咱们能够经过下面的构造方法来初始化一个URL对象: (1) public URL (String spec); 经过一个表示URL地址的字符串能够构造一个URL对象 URL urlBase=new URL("http://www. 263.net/") (2) public URL(URL context, String spec); 经过基URL和相对URL构造一个URL对象。 URL net263=new URL ("http://www.263.net/"); URL index263=new URL(net263, "index.html") (3) public URL(String protocol, String host, String file); new URL("http", "www.gamelan.com", "/pages/Gamelan.net. html"); (4) public URL(String protocol, String host, int port, String file); URL gamelan=new URL("http", "www.gamelan.com", 80, "Pages/Gamelan.network.html");
注意:类URL的构造方法都声明抛弃非运行时例外(MalformedURLException),所以生成URL对象时,咱们必需要对这一例外进行处理,一般是用try-catch语句进行捕获。格式以下:
try{ URL myURL= new URL(…) }catch (MalformedURLException e){ … }
2. 解析一个URL
一个URL对象生成后,其属性是不能被改变的,可是咱们能够经过类URL所提供的方法来获取这些属性: public String getProtocol() 获取该URL的协议名。 public String getHost() 获取该URL的主机名。 public int getPort() 获取该URL的端口号,若是没有设置端口,返回-1。 public String getFile() 获取该URL的文件名。 public String getRef() 获取该URL在文件中的相对位置。 public String getQuery() 获取该URL的查询信息。 public String getPath() 获取该URL的路径 public String getAuthority() 获取该URL的权限信息 public String getUserInfo() 得到使用者的信息 public String getRef()得到该URL的锚
3.从URL读取WWW网络资源
当咱们获得一个URL对象后,就能够经过它读取指定的WWW资源。这时咱们将使用URL的方法openStream(),其定义为: InputStream openStream(); 方法openSteam()与指定的URL创建链接并返回InputStream类的对象以从这一链接中读取数据。 URL url = new URL("http://www.baidu.com");
//使用openStream获得一输入流并由此构造一个BufferedReader对象
BufferedReader br = new BufferedReader(new InputStreamReader( url.openStream()));
String line = null;
while(null != (line = br.readLine()))
{
System.out.println(line);
}
br.close();
三:客户端网络编程步骤
按照前面的基础知识介绍,不管使用TCP方式仍是UDP方式进行网络通信,网络编程都是由客户端和服务器端组成
1.客户端网络编程步骤
客户端(Client)是指网络编程中首先发起链接的程序,客户端通常实现程序界面和基本逻辑实现,在进行实际的客户端编程时,不管客户端复杂仍是简单,以及客户端实现的方式,客户端的编程主要由三个步骤实现:
1、 创建网络链接
客户端网络编程的第一步都是创建网络链接。在创建网络链接时须要指定链接到的服务器的IP地址和端口号,创建完成之后,会造成一条虚拟的链接,后续的操做就能够经过该链接实现数据交换了。
2、 交换数据
链接创建之后,就能够经过这个链接交换数据了。交换数据严格按照请求响应模型进行,由客户端发送一个请求数据到服务器,服务器反馈一个响应数据给客户端,若是客户端不发送请求则服务器端就不响应。
根据逻辑须要,能够屡次交换数据,可是仍是必须遵循请求响应模型。
3、 关闭网络链接
在数据交换完成之后,关闭网络链接,释放程序占用的端口、内存等系统资源,结束网络编程。
最基本的步骤通常都是这三个步骤,在实际实现时,步骤2会出现重复,在进行代码组织时,因为网络编程是比较耗时的操做,因此通常开启专门的现场进行网络通信。
2.服务器端网络编程步骤
服务器端(Server)是指在网络编程中被动等待链接的程序,服务器端通常实现程序的核心逻辑以及数据存储等核心功能。服务器端的编程步骤和客户端不一样,是由四个步骤实现,依次是:
1、 监听端口
服务器端属于被动等待链接,因此服务器端启动之后,不须要发起链接,而只须要监听本地计算机的某个固定端口便可。
这个端口就是服务器端开放给客户端的端口,服务器端程序运行的本地计算机的IP地址就是服务器端程序的IP地址。
2、 得到链接
当客户端链接到服务器端时,服务器端就能够得到一个链接,这个链接包含客户端的信息,例如客户端IP地址等等,服务器端和客户端也经过该链接进行数据交换。
通常在服务器端编程中,当得到链接时,须要开启专门的线程处理该链接,每一个链接都由独立的线程实现。
3、 交换数据
服务器端经过得到的链接进行数据交换。服务器端的数据交换步骤是首先接收客户端发送过来的数据,而后进行逻辑处理,再把处理之后的结果数据发送给客户端。简单来讲,就是先接收再发送,这个和客户端的数据交换数序不一样。
其实,服务器端得到的链接和客户端链接是同样的,只是数据交换的步骤不一样。
固然,服务器端的数据交换也是能够屡次进行的。
在数据交换完成之后,关闭和客户端的链接。
4、 关闭链接
当服务器程序关闭时,须要关闭服务器端,经过关闭服务器端使得服务器监听的端口以及占用的内存能够释放出来,实现了链接的关闭。
四:一个基础的网络类——InetAddress类
该类的功能是表明一个IP地址,而且将IP地址和域名相关的操做方法包含在该类的内部。
关于该类的使用,下面经过一个基础的代码示例演示该类的使用,代码以下:
public class InetAddressDemo { public static void main(String[] args) { try { // 使用域名建立对象 InetAddress inet1 = InetAddress.getByName("www.163.com"); System.out.println(inet1); // 使用IP建立对象 InetAddress inet2 = InetAddress.getByName("127.0.0.1"); System.out.println(inet2); // 得到本机地址对象 InetAddress inet3 = InetAddress.getLocalHost(); System.out.println(inet3); // 得到对象中存储的域名 String host = inet3.getHostName(); System.out.println("域名:" + host); // 得到对象中存储的IP String ip = inet3.getHostAddress(); System.out.println("IP:" + ip); } catch (Exception e) { } } }
注:InetAddress 类没有明显的构造函数。为生成一个InetAddress对象,必须运用一个可用的工厂方法。
–工厂方法(factory method)仅是一个类中静态方法返回一个该类实例的约定。对于InetAddress,三个方法 getLocalHost( )、getByName( )以及getAllByName( )能够用来建立InetAddress的实例
•若是这些方法不能解析主机名,它们引起一个UnknownHostException异常。
五:TCP编程
在Java语言中,对于TCP方式的网络编程提供了良好的支持,在实际实现时,以java.net.Socket类表明客户端链接,以java.net.ServerSocket类表明服务器端链接。在进行网络编程时,底层网络通信的细节已经实现了比较高的封装,因此在程序员实际编程时,只须要指定IP地址和端口号码就能够创建链接了。
在客户端网络编程中,首先须要创建链接,在Java API中以java.net.Socket类的对象表明网络链接
客户端
1) 创建Socket链接
Socket socket2 = new Socket(“www.sohu.com”,80);
2)按照“请求-响应”模型进行网络数据交换
在Java语言中,数据传输功能由Java IO实现,也就是说只须要从链接中得到输入流和输出流便可,而后将须要发送的数据写入链接对象的输出流中,在发送完成之后从输入流中读取数据便可。示例代码以下:
OutputStream os = socket1.getOutputStream(); //得到输出流
InputStream is = socket1.getInputStream(); //得到输入流
这里得到的只是最基本的输出流和输入流对象,还能够根据前面学习到的IO知识,使用流的嵌套将这些得到到的基本流对象转换成须要的装饰流对象,从而方便数据的操做。
3)关闭网络链接
socket1.close();
服务器端
首先须要说明的是,客户端的步骤和服务器端的编写步骤不一样,因此在学习服务器端编程时注意不要和客户端混淆起来。
1)监听端口
ServerSocket ss = new ServerSocket(10000);
2)得到链接
当有客户端链接到达时,创建一个和客户端链接对应的Socket连 接对象,从而释放客户端链接对于服务器端端口的占用
Socket socket = ss.accept();
该代码实现的功能是得到当前链接到服务器端的客户端链接。须要说明的是accept和前面IO部分介绍的read方法同样,都是一个阻塞方法,也就是当无链接时,该方法将阻塞程序的执行,直到链接到达时才执行该行代码。另外得到的链接会在服务器端的该端口注册,这样之后就能够经过在服务器端的注册信息直接通讯,而注册之后服务器端的端口就被释放出来,又能够继续接受其它的链接了。
3)按照“请求-响应”模型进行网络数据交换
这里得到的Socket类型的链接就和客户端的网络链接同样了,只是服务器端须要首先读取发送过来的数据,而后进行逻辑处理之后再发送给客户端,也就是交换数据的顺序和客户端交换数据的步骤恰好相反
InputStream is = ss.getInputStream(); //得到输入流
OutputStream os = ss.getOutputStream(); //得到输出流
4)关闭服务器端链接
ss.close();
以上就是基本的TCP类型的服务器和客户端代码实现的步骤,下面以一个简单的echo(回声)服务实现为例子,介绍综合使用示例,实现的代码以下:
public class Constants { 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) { } } } }
UDP编程
UDP(User Datagram Protocol),中文意思是用户数据报协议使用该种方式无需创建专用的虚拟链接,因为无需创建专用的链接,因此对于服务器的压力要比TCP小不少,因此也是一种常见的网络编程方式。可是使用该种方式最大的不足是传输不可靠,固然也不是说常常丢失,就像你们发短信息同样,理论上存在收不到的可能
在Java API中,实现UDP方式的编程,包含客户端网络编程和服务器端网络编程,主要由两个类实现,分别是:
l DatagramSocket
DatagramSocket类实现“网络链接”,包括客户端网络链接和服务器端网络链接。虽然UDP方式的网络通信不须要创建专用的网络链接,可是毕竟仍是须要发送和接收数据,DatagramSocket实现的就是发送数据时的发射器,以及接收数据时的监听器的角色。类比于TCP中的网络链接,该类既能够用于实现客户端链接,也能够用于实现服务器端链接。
l DatagramPacket
DatagramPacket类实现对于网络中传输的数据封装,也就是说,该类的对象表明网络中交换的数据。在UDP方式的网络编程中,不管是须要发送的数据仍是须要接收的数据,都必须被处理成DatagramPacket类型的对象,该对象中包含发送到的地址、发送到的端口号以及发送的内容等。其实DatagramPacket类的做用相似于现实中的信件,在信件中包含信件发送到的地址以及接收人,还有发送的内容等,邮局只须要按照地址传递便可。在接收数据时,接收到的数据也必须被处理成DatagramPacket类型的对象,在该对象中包含发送方的地址、端口号等信息,也包含数据的内容。和TCP方式的网络传输相比,IO编程在UDP方式的网络编程中变得不是必须的内容,结构也要比TCP方式的网络编程简单一些。
UDP客户端编程涉及的步骤也是4个部分:创建链接、发送数据、接收数据和关闭链接。
1)创建链接:
DatagramSocket ds = new DatagramSocket();
该客户端链接使用系统随机分配的一个本地计算机的未用端口号
固然,能够经过制定链接使用的端口号来建立客户端链接。
DatagramSocket ds = new DatagramSocket(5000);
通常在创建客户端链接时没有必要指定端口号码。
2)发送数据
在发送数据时,须要将须要发送的数据内容首先转换为byte数组,而后将数据内容、服务器IP和服务器端口号一块儿构形成一个DatagramPacket类型的对象,这样数据的准备就完成了了,发送时调用网络链接对象中的send方法发送该对象便可
代码示例:
String s = "Hello";
String host = "127.0.0.1";
int port = 10001;
//将发送的内容转换为byte数组
byte[] b = s.getBytes();
//将服务器IP转换为InetAddress对象
InetAddress server = InetAddress.getByName(host);
//构造发送的数据包对象
DatagramPacket sendDp = new DatagramPacket(b,b.length,server,port);
//发送数据
ds.send(sendDp);
在该示例代码中,无论发送的数据内容是什么,都须要转换为byte数组,而后将服务器端的IP地址构形成InetAddress类型的对象,在准备完成之后,将这些信息构形成一个DatagramPacket类型的对象,在UDP编程中,发送的数据内容、服务器端的IP和端口号,都包含在DatagramPacket对象中。在准备完成之后,调用链接对象ds的send方法把DatagramPacket对象发送出去便可。
3)UDP客户端编程中接收数据
首先构造一个数据缓冲数组,该数组用于存储接收的服务器端反馈数据,该数组的长度必须大于或等于服务器端反馈的实际有效数据的长度。而后以该缓冲数组为基础构造一个DatagramPacket数据包对象,最后调用链接对象的receive方法接收数据便可。接收到的服务器端反馈数据存储在DatagramPacket类型的对象内部
示例代码:
//构造缓冲数组 byte[] data = new byte[1024]; //构造数据包对象 DatagramPacket receiveDp = new DatagramPacket(data,data.length); //接收数据 ds.receive(receiveDp); //输出数据内容 byte[] b = receiveDp.getData(); //得到缓冲数组 int len = receiveDp.getLength(); //得到有效数据长度 String s = new String(b,0,len); System.out.println(s);
代码讲解 : 首先构造缓冲数组data,这里设置的长度1024是预估的接收到的数据长度,要求该长度必须大于或等于接收到的数据长度,而后以该缓冲数组为基础,构造数据包对象,使用链接对象ds的receive方法接收反馈数据,因为在Java语言中,除String之外的其它对象都是按照地址传递,因此在receive方法内部能够改变数据包对象receiveDp的内容,这里的receiveDp的功能和返回值相似。数据接收到之后,只须要从数据包对象中读取出来就能够了,使用DatagramPacket对象中的getData方法能够得到数据包对象的缓冲区数组,可是缓冲区数组的长度通常大于有效数据的长度,换句话说,也就是缓冲区数组中只有一部分数据是反馈数据,因此须要使用DatagramPacket对象中的getLength方法得到有效数据的长度,则有效数据就是缓冲数组中的前有效数据长度个内容,这些才是真正的服务器端反馈的数据的内容
4)关闭链接
ds.close();
UDP方式服务器端网络编程
1)首先UDP方式服务器端网络编程须要创建一个链接,该链接监听某个端口:
DatagramSocket ds = new DatagramSocket(10010);
因为服务器端的端口须要固定,因此通常在创建服务器端链接时,都指定端口号
2)接收客户端发送过来的数据
其接收的方法和客户端接收的方法一直,其中receive方法的做用相似于TCP方式中accept方法的做用,该方法也是一个阻塞方法,其做用是接收数据。
ds.receive()
接收到客户端发送过来的数据之后,服务器端对该数据进行逻辑处理,而后将处理之后的结果再发送给客户端,在这里发送时就比客户端要麻烦一些,由于服务器端须要得到客户端的IP和客户端使用的端口号,这个均可以从接收到的数据包中得到。示例代码以下:
//得到客户端的IP
InetAddress clientIP = receiveDp.getAddress();
//得到客户端的端口号
Int clientPort = receiveDp.getPort();
3)关闭链接
ds.close()
好了,占时就总结到这吧,总结的不是很全面,但很基础,应该适合初学者学习,因为本人也是初学者的小菜鸟,全部不少东西可能都涉及不到,但愿你们见谅!
本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.csdn.net/csh624366188