黑马程序员—JAVA基础之网络编程

来源:互联网 发布:km算法 c 代码实现 编辑:程序博客网 时间:2024/05/22 06:55

网络编程

TCP

    TCP方式的网络通讯是指在通讯的过程中保持连接,有点类似于打电话,只需要拨打一次号码(建立一次网络连接),就可以多次通话(多次传输数据)。这样方式在实际的网络编程中,由于传输可靠,类似于打电话,如果甲给乙打电话,乙说没有听清楚让甲重复一遍,直到乙听清楚为止,实际的网络传输也是这样,如果发送的一方发送的数据接收方觉得有问题,则网络底层会自动要求发送方重发,直到接收方收到为止。

下面是一个简单的网络客户端程序示例:

     该程序的作用是向服务器端发送一个字符串“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) {}

}

}

}

    该代码建立了一个连接到IP地址为127.0.0.1,端口号码为10000的TCP类型的网络连接,然后获得连接的输出流对象,将需要发送的字符串“Hello”转换为byte数组写入到输出流中,由系统自动完成将输出流中的数据发送出去,如果需要强制发送,可以调用输出流对象中的flush方法实现。在数据发送出去以后,从连接对象的输入流中读取服务器端的反馈信息,读取时可以使用IO中的各种读取方法进行读取,这里使用最简单的方法进行读取,从输入流中读取到的内容就是服务器端的反馈,并将读取到的内容在客户端的控制台进行输出,最后依次关闭打开的流对象和网络连接对象。

    这是一个简单的功能示例,在该示例中演示了TCP类型的网络客户端基本方法的使用,该代码只起演示目的,还无法达到实用的级别。

    如果需要在控制台下面编译和运行该代码,需要首先在控制台下切换到源代码所在的目录,然后依次输入编译和运行命令:

    javac –d . SimpleSocketClient.java

    java tcp.SimpleSocketClient


    在服务器端程序编程中,由于服务器端实现的是被动等待连接,所以服务器端编程的第一个步骤是监听端口,也就是监听是否有客户端连接到达。实现服务器端监听的代码为:

ServerSocket ss = new ServerSocket(10000);

    该代码实现的功能是监听当前计算机的10000号端口,如果在执行该代码时,10000号端口已经被别的程序占用,那么将抛出异常。否则将实现监听。

    服务器端编程的第二个步骤是获得连接。该步骤的作用是当有客户端连接到达时,建立一个和客户端连接对应的Socket连 接对象,从而释放客户端连接对于服务器端端口的占用。实现功能就像公司的前台一样,当一个客户到达公司时,会告诉前台我找某某某,然后前台就通知某某某, 然后就可以继续接待其它客户了。通过获得连接,使得客户端的连接在服务器端获得了保持,另外使得服务器端的端口释放出来,可以继续等待其它的客户端连接。 实现获得连接的代码是:

Socket socket = ss.accept();

最后,在服务器端通信完成以后,关闭服务器端连接。实现的代码为:

ss.close();

    下面以一个简单的echo服务实现为例子,介绍综合使用示例。echo的意思就是“回声”,echo服务器端实现的功能就是将客户端发送的内容再原封不动的反馈给客户端。实现的代码如下:


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){}

}

}

}

 

 

UDP

    网络通讯的方式除了TCP方式以外,还有一种实现的方式就是UDP方式。UDP(User Datagram Protocol),中文意思是用户数据报协议,方式类似于发短信息,是一种物美价廉的通讯方式,使用该种方式无需建立专用的虚拟连接,由于无需建立专用的连接,所以对于服务器的压力要比TCP小很多,所以也是一种常见的网络编程方式。但是使用该种方式最大的不足是传输不可靠,就像大家发短信息一样,理论上存在收不到的可能,这种可能性可能是1%,反正比较小,但是由于这种可能的存在,所以平时我们都觉得重要的事情还是打个电话(就像TCP方式),一般的事情才发短信息(类似UDP方式)。网络编程中也是这样,必须要求可靠传输的信息一般使用TCP方式实现,一般的数据才使用UDP方式实现。

    UDP方式的网络编程也在Java语言中获得了良好的支持,由于其在传输数据的过程中不需要建立专用的连接等特点,所以在Java API中设计的实现结构和TCP方式不太一样。当然,需要使用的类还是包含在java.net包中。

在Java API中,实现UDP方式的编程,包含客户端网络编程和服务器端网络编程,主要由两个类实现,分别是:

DatagramSocket

    DatagramSocket类实现“网络连接”,包括客户端网络连接和服务器端网络连接。虽然UDP方式的网络通讯不需要建立专用的网络连接,但还是需要发送和接收数据,DatagramSocket实现的就是发送数据时的发射器,以及接收数据时的监听器的角色。类比于TCP中的网络连接,该类既可以用于实现客户端连接,也可以用于实现服务器端连接。

DatagramPacket

    DatagramPacket类实现对于网络中传输的数据封装,也就是说,该类的对象代表网络中交换的数据。在UDP方式的网络编程中,无论是需要发送的数据还是需要接收的数据,都必须被处理成DatagramPacket类型的对象,该对象中包含发送到的地址、发送到的端口号以及发送的内容等。其实DatagramPacket类的作用类似于现实中的信件,在信件中包含信件发送到的地址以及接收人,还有发送的内容等,邮局只需要按照地址传递即可。在接收数据时,接收到的数据也必须被处理成DatagramPacket类型的对象,在该对象中包含发送方的地址、端口号等信息,也包含数据的内容。和TCP方式的网络传输相比,IO编程在UDP方式的网络编程中变得不是必须的内容,结构也要比TCP方式的网络编程简单一些。

    UDP方式的网络编程,编程的步骤和TCP方式类似,只是使用的类和方法存在比较大的区别,下面首先介绍一下UDP方式的网络编程客户端实现过程。

    UDP客户端编程涉及的步骤也是4个部分:建立连接、发送数据、接收数据和关闭连接。


    UDP方式的建立连接和TCP方式不同,只需要建立一个连接对象即可,不需要指定服务器的IP和端口号码。

      实现的代码为:DatagramSocket ds = new DatagramSocket();

 这样就建立了一个客户端连接,该客户端连接使用系统随机分配的一个本地计算机的未用端口号。在该连接中,不指定服务器端的IP和端口,所以UDP方式的网络连接更像一个发射器,而不是一个具体的连接。

当然,可以通过制定连接使用的端口号来创建客户端连接。

DatagramSocket ds = new DatagramSocket(5000);

这样就是使用本地计算机的5000号端口建立了一个连接。一般在建立客户端连接时没有必要指定端口号码。

    在UDP方式的网络编程中,IO技术不是必须的,在发送数据时,需要将需要发送的数据内容首先转换为byte数组,然后将数据内容、服务器IP和服务器端口号一起构造成一个DatagramPacket类型的对象,这样数据的准备就完成了,发送时调用网络连接对象中的send方法发送该对象即可。例如将字符串“Hello”发送到IP是127.0.0.1,端口号是10001的服务器,则实现发送数据的代码如下:

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对象发送出去即可。

 

TCP和UDP总结:

面向连接的TCP

    "面向连接"就是在正式通信前必须要与对方建立起连接。比如你给别人打电话,必须等线路接通了、
对方拿起话筒才能相互通话。

    TCP(Transmission Control Protocol,传输控制协议)是基于连接的协议,也就是说,在正式收发
数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次"对话"才能建立起来,首先主机A向
主机B发出连接请求数据包,然后主机B向主机A发送同意连接和要求同步(同步就是两台主机一个发送,
一个接收,协调工作)的数据包,最后主机A再发出一个数据包确认主机B的要求同步。三次"对话"的目
的是使数据包的发送和接收同步,经过三次"对话"之后,主机A才向主机B正式发送数据。


面向非连接的UDP协议

    "面向无连接"就是在正式通信前不必与对方先建立连接,不管对方状态就直接发送。这与现在的手机短
信非常相似:你在发短信的时候,只需要输入对方手机号就OK了。

UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是面向非连接的协议,它不
与对方建立连接,而是直接就把数据包发送过去!

不同之处在于:
    TCP协议能为应用程序提供可靠的通信连接,使一台计算机发出的字节流无差错地发往网络上的其他计算机,对可靠性要求高的数据通信系统往往使用TCP协议传输数据。

    UDP适用于一次只传送少量数据、对可靠性要求不高的应用环境。比如,我们经常使用"ping"命令来测
试两台主机之间TCP/IP通信是否正常,其实"ping"命令的原理就是向对方主机发送UDP数据包,然后对方
主机确认收到数据包,如果数据包是否到达的消息及时反馈回来,那么网络就是通的。例如,在默认状
态下,一次"ping"操作发送4个数据包。发送的数据包数量是4包,收到的也是4包(因为对方主机收到
后会发回一个确认收到的数据包)。这充分说明了UDP协议是面向非连接的协议,没有建立连接的过程。
正因为UDP协议没有连接的过程,所以它的通信效果高;但也正因为如此,牺牲了可靠性。

 

0 0