Java中网络编程

网络

一、TCP和UDP的区别

       1、TCP是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作。

       2、UDP是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。

UDP

  1. 将数据及源和目的封装成数据包中,不需要建立连接
  2. 每个数据报的大小在限制在64k内
  3. 因无连接,是不可靠协议
  4. 不需要建立连接,速度快

UDP就像是在邮局邮递包裹。只管发送,不管对方能不能收到。

TCP

  1. 建立连接,形成传输数据的通道。
  2. 在连接中进行大数据量传输
  3. 通过三次握手完成连接,是可靠协议
  4. 必须建立连接,效率会稍低

TCP就像是打电话,必须接通之后才能说话。

TCP的三次握手协议:

     1.客户端发送一个连接请求到服务器,如果没有收到响应或者服务器返回失败则客户端返回失败,不能正确连接。

     2.服务器端在接收到连接请求后,发回一个同意请求连接,返回给客户端,并且等待客户端的第三次回应,如果没有回应,服务器端关闭连接。

     3.客户端端收到服务器的同意请求后,再次发送一个同意连接。至此连接建立。剩下的就是TCP数据交互过程。

二、建立网络连接

服务器与客户端通过建立soket套接字进行通信,套接字其实就是地址与端口号的组合

UDP客户端编程涉及的步骤是4个部分:

使用到的类:DatagramSocket与DatagramPacket

  1.  获取socket对象                     
  2. 对数据进行封包                     
  3. 通过socket对象把数据包发送出去     
  4. 把连接关闭   

TCP服务端编程涉及的步骤是4个部分:

  1. 使用到的类Socket和ServerSocket
  2. 建立客户端和服务器端
  3. 建立连接后,通过Socket中的IO流进行数据的传输
  4. 关闭socket
同样,客户端与服务器端是两个独立的应用程序。

程序实例

UDP:

Server端:

package net;

import java.net.*;
import java.io.*;

public class TestUDPServer {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		byte buf[] = new byte[1024];
		DatagramPacket dp = new DatagramPacket(buf,buf.length);
		DatagramSocket ds = new DatagramSocket(5678);
		while(true){
			ds.receive(dp);
			ByteArrayInputStream bais = new ByteArrayInputStream(buf);     //从字节数组中读取数据
			DataInputStream dis = new DataInputStream(bais);    //将字节转化成LONG类型的数
			System.out.println(dis.readLong());    //将字节数组构建成一个字符串
		}
	}

}
Client端:
package net;

import java.net.*;
import java.io.*;

public class TestUDPClient {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		long n = 1000000L;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();    //在内存中创建了一个字节数组,将一根管道连接到这块内存中
		DataOutputStream dos = new DataOutputStream(baos);
		dos.writeLong(n);   //将这个数据写到相应的内存中
		byte[] buf = baos.toByteArray();    //将内存中的数据转换成字节数组
		DatagramPacket dp = new DatagramPacket(buf,buf.length,new InetSocketAddress("127.0.0.1",5678));
		DatagramSocket ds = new DatagramSocket(9999);
		ds.send(dp);
		ds.close();
	}

}

TCP:

Server端:

import java.net.*;
import java.io.*;

public class TCPServer {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		ServerSocket ss = new ServerSocket(6666);    //规定连接的端口
		while(true){
			Socket s = ss.accept();      //接受连接    阻塞式
			DataInputStream dis = new DataInputStream(s.getInputStream());
			System.out.println(dis.readUTF());   //阻塞式
			dis.close();
			s.close();
		}
		
	}

}
Client端:

package net;

import java.io.*;
import java.net.*;

public class TCOClient {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		Socket s = new Socket("127.0.0.1",8189);  //申请链接
		OutputStream os = s.getOutputStream();
		DataOutputStream dos = new DataOutputStream(os);
		dos.writeUTF("hello server!");
		dos.flush();
		dos.close();
		s.close();
	}

}

以上是应用TCP和UDP进行通信的两个实例

三、问题

1、套接字超时

    在套接字读取信息的时候,读取操作阻塞,最终会受到底层操作系统的影响导致超时,为了不让阻塞时间过长,我们可以设置合理的超时时间。

    setSoTimeout方法为套接字设置了超时值,但是当读写操作未完成的时候达到了超时时间,抛出SocketTimeoutException异常。

    当客户端请求服务器端连接的时候,超时。

应该用connet(new InetSocketAddress(host,port),timeout);构建套接字并且设置超时时间。

    例:Socket s = new Socket();

        s.connect(new InetSocketAddress(host,port),timeout);

2、因特网地址

   在主机名和网络地址之间进行转换可以应用InetAddress类对象

代码:

import java.net.InetAddress;
import java.net.UnknownHostException;

public class InetAddressTest {

	public static void main(String[] args) throws UnknownHostException {
		if(args.length > 0){
			String host = args[0];
			InetAddress [] addresses = InetAddress.getAllByName(host);
			for(InetAddress a : addresses) {
				System.out.println(a);
			}
		}
		else{
			InetAddress localHostAddress = InetAddress.getLocalHost();   //获取本地地址
			InetAddress address = InetAddress.getByName("time-A.timefreq.bldrdoc.gov");    //获取地址
			InetAddress[] address1 = InetAddress.getAllByName("baidu.com");   //获取所有的主机
			System.out.println(address.getHostName());
			System.out.println(address);
			System.out.println(localHostAddress);
			for(int i = 0; i < address1.length; i++){
				System.out.println(address1[i]);
			}
			
		}
	}

}

3、半关闭套接字

   功能:套接字连接的一端可以终止其输出,同时仍旧可以接收来自另一端的数据。使用于一站式的服务

   实现:Socket socket = new Socket(host,post);

         socket.shutdownOutput();

4、可中断套接字

    在我们平时点解连接的时候,往往会有一个终止访问的按钮,用来终止当前的访问,但是当一个线程被阻塞的时候,无法进行和用户的交互,直至操作成功或者超时。

    应用java.nio包中提供的一个新特性SocketChannel类实现。

    SocketChannel channel = new SocketChannel.open(new InetSocketAddress(host,port));

    通道没有与之相对应对的流,在不处理缓冲区的情况下,可使用Scanner类从SocketChannel中读取信息,Scanner in = new Scanner(channel);

    OutputStream outStream = Channels.newOutputStream(channel);

    这样可以中断一个阻塞的线程,当这个套接字发成阻塞的时候可以进行中断操作。

5、URL和URI

    URL是统一资源定位符,URI是统一资源标识符。URL是URI的一种特例。URN是统一资源名称。

URL 解析:

  • 协议为(protocol):http
  • 主机为(host:port):www.runoob.com
  • 端口号为(port): 80 ,以上URL实例并未指定端口,因为 HTTP 协议默认的端口号为 80。
  • 文件路径为(path):/index.html
  • 请求参数(query):language=cn
  • 定位位置(fragment):j2se,定位到网页中 id 属性为 j2se 的 HTML 元素位置 。

    在java.net包中定义了URL类,该类用来处理有关URL的内容。对于URL类的创建和使用,下面分别进行介绍。java.net.URL提供了丰富的URL构建方式,并可以通过java.net.URL来获取资源。

    URLConnection类为解析URL提供了更多的方法,

    URLConnection connection = url.openConnection();

    具体的方法可参考API.

6、端口

    端口号范围为0到65535,其中0到1023的端口号一般分配给一些服务。比如FTP服务(21),SMTP(25)服务,HTTP(25)服务,135分配给RPC(远程过程调用)等;从1024到65535的端口号供用户自定义的服务使用。


注:此博客是作者初学笔记,仅供参考。





猜你喜欢

转载自blog.csdn.net/qq_32270067/article/details/78554540
今日推荐