黑马程序员---网络编程技术

来源:互联网 发布:python案例讲解 编辑:程序博客网 时间:2024/05/01 08:53

java网络编程技术

 

------- android培训    java培训期待与您交流! ----------


网络通讯的方式主要有两种:

1、 TCP(传输控制协议)方式

2、 UDP(用户数据报协议)方式

为 了方便理解这两种方式,还是先来看一个例子。大家使用手机时,向别人传递信息时有两种方式:拨打电话和发送短信。使用拨打电话的方式可以保证将信息传递给 别人,因为别人接听电话时本身就确认接收到了该信息。而发送短信的方式价格低廉,使用方便,但是接收人有可能接收不到。

在网络通讯中,TCP方式就类似于拨打电话,使用该种方式进行网络通讯时,需要建立专门的虚拟连接,然后进行可靠的数据传输,如果数据发送失败,则客户端会自动重发该数据。而UDP方式就类似于发送短信,使用这种方式进行网络通讯时,不需要建立专门的虚拟连接,传输也不是很可靠,如果发送失败则客户端无法获得。

这两种传输方式都是实际的网络编程中进行使用,重要的数据一般使用TCP方式进行数据传输,而大量的非核心数据则都通过UDP方式进行传递,在一些程序中甚至结合使用这两种方式进行数据的传递。

由于TCP需要建立专用的虚拟连接以及确认传输是否正确,所以使用TCP方式的速度稍微慢一些,而且传输时产生的数据量要比UDP稍微大一些。 


OSI参考模型的全称是开放系统互连参考模型,它是由国际化标准组织ISO提出的一个网络系统互连模型。ISO组织把网络通讯工作分为7层,一到四层被认为是低层, 这些层与数据移动密切相关,5到7层是高层,包含应用程序级的数据,每一层负责一项具体的工作,然后把数据交给下一层。

InetAddress:

用于描述IP的类,主要方法有:
String  getHostAddress();:返回对象IP地址的字符串形式

String  getHostName(); :返回对象的主机名

static   InetAddress  getLocalHost():获取本地主机对象

static   InetAddress  getByName("IP地址"):获取IP地址或者域名获取主机对象。

static  InetAddress[]  getAllByAddress("域名"):通过主机名或者域名获取不同IP地址的主机对象数组。

注:如果IP地址和对应的主机名这个映射关系没有在网络上,其他主机通过IP地址去搜索到了,但是会有没解释成功的情况,getHostName()获取的还是IP的地址;getHostName();会有一个解释过程。

       当输入域名用getByName方法获取主机对象时,IP地址并不是唯一的。因为网络上的服务器可能有多台,对应不用的IP地址,这时就要用:getAllByAddress方法。大部分用getAllByAddress方法为主,因为getHostName方法需要解释。

 

UDP、TCP和Socket

UDP: 1.将数据及源和谜底封装在数据包中,不需要建立连接

       2.每个数据的大小控制在64k内

       3.因无连接,是不可靠协议

       4.不需要建立连接,速度快

 


TCP: 1. 需要建立连接,形成传输数据的通道

       2.在连接中进行大量数据传输

       3.通过三次握手完成连接,是可靠协议

       4.必须要建立连接,效率稍低

 

Socket 套接字:1. Socket 是为网络服务提供的一种机制

              2. 通信的两端都要具有Socket

              3. 网络通信其实就是Socket 间的通信

              4.数据在两个Socket 间通过IO传输

个人理解可以将Socket 理解成码头,A城市的码头将货物运到B码头通过河流运输,A城市电脑A,B城市电脑B,码头:Socket ,货物就是数据,河流就是IO流

 
UDP传输:

1、定义UDPSocket服务,通常会监听一个端口,其实就是给这个接收网络应用程序定义数字标识。方便于明确哪些数据传输过来后是该应用程序可以处理的。

2、定义一个空的数据包,用于存储接收到的字节数据。因为数据包对象中有更多的功能可以崎岖字节数据中的同数据信息。

3通过Socket服务的receive方法接收到的数据存入已定义好的数据包中。

4、通过数据包对象的特有功能,将这些不同的数据取出。

5、关闭资源。

注意:不手动定义端口的话,虚拟机会自动添加一个端口,但是就会和发送端定义的端口对应不上,就接收不到数据。另外,DatagramPacket中的getPort()是获取发送端的自身的端口,而不是发送端的目的端口。

public static void main(String[] args)  throws Exception{DatagramSocket ds = new DatagramSocket(11111);byte[] buf = new byte[1024];DatagramPacket dp = new DatagramPacket(buf,buf.length);String str = null;while(true){ds.receive(dp);str = new String(buf,0,dp.getLength());String ip = dp.getAddress().getHostAddress();System.out.println(ip+"::"+str);}}

TCP传输:

建立客户端和服务端,建立连接后,通过socket的IO流进行数据传输。

 

对客户端和服务端的理解:

客户端:

                  该对象建立时,就可以去连接指定主机,因为TCP是面向连接的,所以在建立Socket服务时,只要有服务在并连接成功形成通路后,该通道进行数据的传输


服务端:

                  1. 建立服务端的Socket服务,ServerSocket(), 并监听一个端口

                  2. 获取连接过来的客户端对象,通过ServerSocket的accept方法,没有连接就会等,所以这个方法是阻塞式的。

                  3.如果客户端发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发来的数据

                  4.关闭服务器

/*演示tcp的传输的客户端和服务端的互访。需求:客户端给服务端发送数据,服务端收到后,给客户端反馈信息。*//*客户端:1,建立socket服务。指定要连接主机和端口。2,获取socket流中的输出流。将数据写到该流中。通过网络发送给服务端。3,获取socket流中的输入流,将服务端反馈的数据获取到,并打印。4,关闭客户端资源。*/import java.io.*;import java.net.*;class myServer2{public static void main(String[] args)  throws Exception{//建立服务端ServerSocket server = new ServerSocket(10022);while(true){//获取客户端对象Socket s = server.accept();String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"...连接服务器!");//客户端对象输出流和读取流//BufferedWriter bfos = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));BufferedReader bfis = new BufferedReader(new InputStreamReader(s.getInputStream()));//简化代码不用BufferedWriter和转换流,用PrintWriter;PrintWriter pw = new PrintWriter(s.getOutputStream(),true);//循环获取客户端信息和进行反馈while(true){String line = bfis.readLine();//当客户端关闭,这里就会返回-1if("over".equals(line))break;System.out.println(ip+"::"+line);pw.println(line.toUpperCase());/*bfos.write(line.toUpperCase());//跟客户端一样,要加上,不然客户端那里也是等待bfos.newLine();bfos.flush();*/}System.out.println(ip+"...以结束连接!");s.close();}}}class  myTcpDemo2{public static void main(String[] args) throws Exception{//客户端连接Socket sock = new Socket("192.168.2.100",10022);//获取键盘录入BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));//客户端输出流和读取流//BufferedWriter bfos = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));BufferedReader bfis = new BufferedReader(new InputStreamReader(sock.getInputStream()));//简化代码不用BufferedWriter和转换流,用PrintWriter;PrintWriter pw = new PrintWriter(sock.getOutputStream(),true);String line = null;while((line=bfr.readLine())!=null){if("over".equals(line)){pw.println(line);/*bfos.write(line);bfos.flush();*/break;}pw.println(line);/*bfos.write(line);//这里要加上newLine方法,不然服务端那里的readLine方法没有读取到换行,就会一直等待bfos.newLine();bfos.flush();*/String str = bfis.readLine();System.out.println("Server::"+str);}bfr.close();sock.close();}}

原创粉丝点击