原文来自搬砖工,如需转载请注明出处
这篇文章简单总结1下java网络编程的相干知识
1、TCP和UDP
1.TCP(传输控制协议)方式
TCP方式就类似于拨打电话,使用该种方式进行网络通讯时,需要建立专门的虚拟连接,然落后行可靠的数据传输,如果数据发送失败,则客户端会自动重发该数据
2. UDP(用户数据报协议)方式
UDP方式就类似于发送短信,使用这类方式进行网络通讯时,不需要建立专门的虚拟连接,传输也不是很可靠,如果发送失败则客户端没法取得
这两种传输方式都是实际的网络编程中进行使用,重要的数据1般使用TCP方式进行数据传输,而大量的非核心数据则都通过UDP方式进行传递,在1些程序中乃至结合使用这两种方式进行数据的传递。由于TCP需要建立专用的虚拟连接和确认传输是不是正确,所以使用TCP方式的速度略微慢1些,而且传输时产生的数据量要比UDP略微大1些。
总结1下UDP和TCP协议的区分
–使用UDP时,每一个数据报中都给出了完全的地址信息,因此无需要建立发送方和接收方的连接。
–对TCP协议,由于它是1个面向连接的协议,在socket之间进行数据传输之前必定要建立连接,所以在TCP中多了1个连接建立的时间
–使用UDP传输数据时是有大小限制的,每一个被传输的数据报必须限定在64KB以内。
–TCP没有这方面的限制,1旦连接建立起来,双方的socket就能够按统1的格式传输大量的数据。
–UDP是1个不可靠的协议,发送方所发送的数据报其实不1定以相同的次序到达接收方。
–TCP是1个可靠的协议,它确保接收方完全正确地获得发送方所发送的全部数据
–TCP在网络通讯上有极强的生命力,例如远程连接(Telnet)和文件传输(FTP)都需要不定长度的数据被可靠地传输。
–相比之下UDP操作简单,而且仅需要较少的监护,因此通经常使用于局域网高可靠性的分散系统中client/server利用程序
2、基于URL的网络编程
1.创建1个URL
为了表示URL, java.NET中实现了类URL。我们可以通过下面的构造方法来初始化1个URL对象:
(1)public URL (String spec);
通过1个表示URL地址的字符串可以构造1个URL对象
URL urlBase=new URL("http://www. 263.Net/")
(2)public URL(URL context, String spec);
通过基URL和相对URL构造1个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对象时,我们必须要对这1例外进行处理,通常是用try-catch语句进行捕获。格式以下:
try{ URL myURL= new URL(…) }catch (MalformedURLException e){ … }2. 解析1个URL
public String getProtocol() 获得该URL的协议名。 public String getHost() 获得该URL的主机名。 public int getPort() 获得该URL的端口号,如果没有设置端口,返回⑴。 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 url = new URL("http://www.baidu.com"); //使用openStream得到1输入流并由此构造1个BufferedReader对象 BufferedReader br = new BufferedReader(new InputStreamReader( url.openStream())); String line = null; while(null != (line = br.readLine())) { System.out.println(line); } br.close();3、客户端网络编程步骤
4、InetAddress
该类的功能是代表1个IP地址,并且将IP地址和域名相干的操作方法包括在该类的内部。
关于该类的使用,下面通过1个基础的代码示例演示该类的使用,代码以下:
import java.net.InetAddress; 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 类没有明显的构造函数。为生成1个InetAddress对象,必须应用1个可用的工厂方法。
5、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)取得连接
当有客户端连接到达时,建立1个和客户端连接对应的Socket连 接对象,从而释放客户端连接对服务器端端口的占用
Socket socket = ss.accept();
该代码实现的功能是取得当前连接到服务器真个客户端连接。需要说明的是accept和前面IO部份介绍的read方法1样,都是1个阻塞方法,也就是当无连接时,该方法将阻塞程序的履行,直到连接到达时才履行该行代码。另外取得的连接会在服务器真个该端口注册,这样以后就能够通过在服务器真个注册信息直接通讯,而注册以后服务器真个端口就被释放出来,又可以继续接受其它的连接了。
3)依照“要求-响应”模型进行网络数据交换
这里取得的Socket类型的连接就和客户真个网络连接1样了,只是服务器端需要首先读取发送过来的数据,然落后行逻辑处理以后再发送给客户端,也就是交换数据的顺序和客户端交换数据的步骤恰好相反
InputStream is = ss.getInputStream(); //取得输入流
OutputStream os = ss.getOutputStream(); //取得输出流
4)关闭服务器端连接
ss.close();
以上就是基本的TCP类型的服务器和客户端代码实现的步骤,下面以1个简单的echo(回声)服务实现为例子,介绍综合使用示例,实现的代码以下:
import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; 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) { } } } }6、UDP编程
UDP(User Datagram Protocol),中文意思是用户数据报协议使用该种方式无需建立专用的虚拟连接,由于无需建立专用的连接,所以对服务器的压力要比TCP小很多,所以也是1种常见的网络编程方式。但是使用该种方式最大的不足是传输不可靠,固然也不是说常常丢失,就像大家发短信息1样,理论上存在收不到的可能
在Java API中,实现UDP方式的编程,包括客户端网络编程和服务器端网络编程,主要由两个类实现,分别是:
l DatagramSocket
DatagramSocket类实现“网络连接”,包括客户端网络连接和服务器端网络连接。虽然UDP方式的网络通讯不需要建立专用的网络连接,但是毕竟还是需要发送和接收数据,DatagramSocket实现的就是发送数据时的发射器,和接收数据时的监听器的角色。类比于TCP中的网络连接,该类既可以用于实现客户端连接,也能够用于实现服务器端连接。
l DatagramPacket
DatagramPacket类实现对网络中传输的数据封装,也就是说,该类的对象代表网络中交换的数据。在UDP方式的网络编程中,不管是需要发送的数据还是需要接收的数据,都必须被处理成DatagramPacket类型的对象,该对象中包括发送到的地址、发送到的端口号和发送的内容等。其实DatagramPacket类的作用类似于现实中的信件,在信件中包括信件发送到的地址和接收人,还有发送的内容等,邮局只需要依照地址传递便可。在接收数据时,接收到的数据也必须被处理成DatagramPacket类型的对象,在该对象中包括发送方的地址、端口号等信息,也包括数据的内容。和TCP方式的网络传输相比,IO编程在UDP方式的网络编程中变得不是必须的内容,结构也要比TCP方式的网络编程简单1些。
UDP客户端编程触及的步骤也是4个部份:建立连接、发送数据、接收数据和关闭连接。
1)建立连接:
DatagramSocket ds = new DatagramSocket();
该客户端连接使用系统随机分配的1个本地计算机的未用端口号
固然,可以通过制定连接使用的端口号来创建客户端连接。
DatagramSocket ds = new DatagramSocket(5000);
1般在建立客户端连接时没有必要指定端口号码。
2)发送数据
在发送数据时,需要将需要发送的数据内容首先转换为byte数组,然后将数据内容、服务器IP和服务器端口号1起构造成1个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类型的对象,在准备完成以后,将这些信息构造成1个DatagramPacket类型的对象,在UDP编程中,发送的数据内容、服务器真个IP和端口号,都包括在DatagramPacket对象中。在准备完成以后,调用连接对象ds的send方法把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方法可以取得数据包对象的缓冲区数组,但是缓冲区数组的长度1般大于有效数据的长度,换句话说,也就是缓冲区数组中只有1部份数据是反馈数据,所以需要使用DatagramPacket对象中的getLength方法取得有效数据的长度,则有效数据就是缓冲数组中的前有效数据长度个内容,这些才是真实的服务器端反馈的数据的内容
//取得客户真个IP InetAddress clientIP = receiveDp.getAddress(); //取得客户真个端口号 Int clientPort = receiveDp.getPort();3)关闭连接
ps:总结的不是很全面,但很基础,应当合适初学者学习,由于本人也是初学者的小菜鸟,所有很多东西可能都触及不到,希望大家见谅!