JavaSE(8):java网络编程技术


八、Java网络编程技术

 

1、网络通信基础知识

网络通信指网络中的计算机通过网络互相传递信息。

通信协议是网络通信的基础,通信协议是网络中计算机之间进行通信时共同遵守的规定

常用的通信协议:HTTPFTPTCP/IP

常用的网络通信模型:客户/服务器(Client/Serverc/s,胖客户模型)结构;浏览器/服务器(Browser/ServerB/S,瘦客户)结构。

IP地址:网络中任意一台计算机地址的唯一标识。

域名地址:可看做是IP地址的助记名。

端口号:端口是一台主机上标识多个进程的一种手段,主机IP和端口组合能唯一确定网络通信的主体——进程。065535,其中01024是系统使用或保留端口,102465535则为用户使用端口。

网络编程中有两个主要的问题:如何准确地定位网络上一台或多台主机;找到主机后如何可靠高效地进行数据传输。

三种常用的Java网络程序设计:URL编程(支持多种协议,获取远端计算机上的资源信息),TCP编程(使用套接字Socket机制,建立稳定连接,使用流传输数据,C/S构架的主要方式),UDP编程(无连接的快速通信技术,传递数据大且非关键性的数据)。

 

2、URL编程技术

URL对象通常包含最基本的三个部分信息:协议(常用HTTPFTP)、地址、资源。

URLUniform Resource Locator,是网络资源的指针。

URL格式:传输协议名://主机名:端口号/文件名#引用,其中端口号、文件名和引用是可选的,传输协议名和主机名是必须的。

URL类、URLConnection类:URLConnection类用于应用程序与URL之间的连接。该类对象可以读写URL对象所表示的Internet上的数据。一般使用方法如下:

① 通过在URL上调用openConnection方法创建连接对象;

② 处理设置参数和一般请求属性;

③ 使用connect方法连接到远程对象的实际连接;

④ 远程对象变为可用,远程对象的头字段和内容变为可访问。

TestURL.java(两个实例,分别为URLURL综合实例)

 

package blog8;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;


/**
 * URL类和URLConnection类的使用
 * 利用URL下载网络资源:以百度首页logo为例
 */
public class TestURL {

	public static void main(String[] args) throws IOException {
		//TestURL.URLTest();
		TestURL.URLDownload();
	}
	
	public static void URLTest() throws IOException{
		//通过URL类获取远端主机上指定的文件内容
		//1、创建URL对象
		URL url = new URL("http://www.baidu.com/index.html");
		//2、创建InputStream对象
		InputStreamReader isr = new InputStreamReader(url.openStream());
		System.out.println("协议:" + url.getProtocol());
		System.out.println("主机:" + url.getHost());
		System.out.println("端口:" + url.getPort());
		System.out.println("路径:" + url.getPath());
		System.out.println("文件:" + url.getFile());
		
		BufferedReader br = new BufferedReader(isr);
		String inputLine;
		System.out.println("文件内容:");
		while( (inputLine = br.readLine()) != null ){
			System.out.println(inputLine);//按行从缓冲输入流循环读字符,直到读完所有行,输出屏幕
		}
		br.close();
	}
	
	//通过URLConnection下载URL指向的资源
	public static void URLDownload() throws IOException{
		URL url = new URL("http://www.baidu.com/img/bdlogo.gif");
		URLConnection urlConnection = url.openConnection();
		//建立IO流进行数据传递:下载
		InputStream in = urlConnection.getInputStream();
		OutputStream out = new FileOutputStream("baiduLogo.gif");
		//数据传递
		byte [] buffer = new byte[1024];
		int len;
		while( (len = in.read(buffer)) != -1){
			out.write(buffer,0,len);
		}
		//关闭资源,百度logo已保存到本地
		out.flush();
		in.close();
		out.close();
		
	}
}


3、TCPUDP协议:两种协议的特点,一个类InetAddress

TCPUDP的比较

① 使用UDPUser Datagram Protocol)协议时,每个数据包中都给出完整的地址信息,因此无需建立发送方和接收方的连接,而使用TCPTransfer Control Protocol)时,是一个面向连接的协议,所以在socket之间进行数据传输前需要建立连接。

② UDP传输数据有大小限制,每个传输包必须在64KB之内,而TCP没有限制。

③ UDP是一个不可靠的协议,发送的数据包不一定以相同顺序到达接收方,有可能丢失。而TCP是一个可靠的协议,确保接收方完全正确获取发送方发送的全部数据,包括顺序。

InetAddress类:该类用来表示主机地址,常用方法:InetAddress getByAddressparam),该方法参数可以ipbyte数组,可以是提供的主机名的String字符串加ip地址byte数组,返回一个InetAddress对象。

TestInetAddress.javaInetAddress类的使用实例)

package blog8;

import java.io.IOException;
import java.net.InetAddress;

public class TestInetAddress {

	public static void main(String[] args) throws IOException {
		// 1、获取给定域名的地址,该类没有public构造器,只能通过静态获取
		InetAddress inetAddress = InetAddress.getByName("www.baidu.com");
		System.out.println(inetAddress.getHostName()); //显示主机名
		System.out.println(inetAddress.getHostAddress());//显示IP地址
		System.out.println(inetAddress);//显示地址的字符串描述
		/*
		 www.baidu.com
		 119.75.217.56
		 www.baidu.com/119.75.217.56
		*/
		
		// 2、获取本机地址
		InetAddress inetAddress1 = InetAddress.getLocalHost();
		System.out.println(inetAddress1.getHostName()); //显示主机名
		System.out.println(inetAddress1.getHostAddress());//显示IP地址
		System.out.println(inetAddress1);//显示地址的字符串描述
		/*
		 2014-0325-1004
		 192.168.1.102
		 2014-0325-1004/192.168.1.102 
		*/
		
		//获取给定IP的主机地址(202.108.22.5百度)
		byte [] ip = new byte[]{(byte)202,(byte)108,(byte)22,(byte)5};
		InetAddress inetAddress3 = InetAddress.getByAddress(ip);
		InetAddress inetAddress4 = InetAddress.getByAddress("百度",ip);
		System.out.println(inetAddress3);//: /202.108.22.5,主机名为给定,为空
		System.out.println(inetAddress4);//: 百度/202.108.22.5,主机名为百度
	}
}

 


4、TCP编程技术

Socket:网络通信两端都有Socket,网络通信也就是socket之间的通信,数据在两个socket之间通过IO传输。一个套接字有IP地址和端口号唯一确定。常分为客户机套接字:socket;服务器端套接字:ServerSocket

TestTCPBySocket.java(基于socketTcp编程,c/s模型;一个完整的聊天室实例)

package blog8;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

import org.junit.Test;

/**
 * 基于socket的Tcp编程,c/s模型;一个服务器与客户端的通信实例
 * 注:此处有待提高,对c/s的模型还是不够清晰,需要一个完整的c/s多人聊天室实例学习!!!!!!
 * 注:关闭资源都是先关闭客户端,再关闭服务器端
 */
//	Tcp编程,网络套接字(socket)通信的一般步骤:
//	1.连接到远程主机;
//	2.绑定到端口;
//	3.接收从远程来的连接请求;
//	4.监听到达的数据;
//	5.发送数据;
//	6.接收数据;
//	7.关闭连接。
public class TestTCPBySocket {
	
	@Test//服务器端的建立
	public void createServerSocket() throws IOException{
		//1.建立服务器端
		ServerSocket serverSocket = new ServerSocket(8080);
		//2.服务器端获取一个socket作为通信用,通过接受连接返回,接受客户端的连接请求,返回一个socket,这是客户端的socket
		Socket socket = serverSocket.accept();
		//3.建立Socket的输出流,进行通信,已发送一句话为例:向客户端的socket发送数据用输出流
		OutputStream out = socket.getOutputStream();
		PrintWriter printWriter = new PrintWriter(out);
		printWriter.println("来自服务端的问候...");
		
		//4.关闭资源,由内到外逐步关闭
		printWriter.close();
		out.close();
		socket.close();
		serverSocket.close();
	}
	
	@Test//客户端的建立
	public void createClintSocket() throws IOException{
		//1.获取主机的地址,本例用本机,所以127.0.0.1
		InetAddress host = InetAddress.getByName("127.0.0.1"); 
		//2.建立服务器的socket套接字,参数为,主机address和连接的端口,这里获取的Socket是客户端的
		Socket socket = new Socket(host,8080); 
		//3.获取服务器socket的IO流,进行通信,这里是读取客户端的socket的数据流,服务器已向客户端Socket输出数据了
		InputStream in = socket.getInputStream();
		//先转换.过程:inputstream -> inputstreamReader -> bufferedReader
		BufferedReader reader = new BufferedReader(new InputStreamReader(in));
		System.out.println(reader.readLine()); //选用BufferedReader对象的行读方式读取
		
		//4.关闭资源
		reader.close();
		socket.close();
	}
}


TestChart.java(服务器与客户端双向通信实例)

package blog8;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import org.junit.Test;

/**
 * 服务器客户端双向通信实例
 */
public class TestChart {

	@Test//1、服务器端
	public void MyServer() throws IOException{
		ServerSocket server = new ServerSocket(2008);
		Socket socket = server.accept();
		
		String ip = socket.getInetAddress().getHostAddress();
		System.out.println(ip + "...connected..");
		
		InputStream in = socket.getInputStream();
		byte [] buffer = new byte[1024];
		int len;
		System.out.println("来自客户端的信息:");
		while( (len=in.read(buffer)) != -1 ){
			System.out.println(new String(buffer,0,len));
		}
		
		OutputStream out = socket.getOutputStream();
		out.write("hello,这里是服务器...".getBytes());
		
		socket.close();
		server.close(); //注意先关闭客户端资源,子关闭服务器端资源
	}
	
	@Test//2、客户端
	public void MyClient() throws IOException{
		Socket socket = new Socket("localhost",2008);//create a connection
		OutputStream out = socket.getOutputStream();
		out.write("这里是客户A,我正在连接服务器...".getBytes());
		
		socket.shutdownOutput(); // 注意,关闭标签!!!!
		
		InputStream in = socket.getInputStream();
		System.out.println("这是服务器给我的回信:");
		byte [] buffer = new byte[1024];
		int len;
		while( (len = in.read(buffer)) != -1 ){
			System.out.println(new String(buffer,0,len));
		}	
	
		socket.close();
	}
}


TestUpload.javaTcp编程应用:文件上传功能)

package blog8;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class TestUpload {
	public static void main(String[] args) throws IOException {
		@SuppressWarnings("resource")
		ServerSocket server = new ServerSocket(8888);
		while(true){ //服务器永远执行、等待
			Socket socket = server.accept(); //服务器接收到客户连接请求
			new Thread(new MyServer(socket)).start();
		}
	}
}

class MyClient{
	public void upload() throws IOException{
		Socket socket = new Socket("localhost",8888);
		OutputStream out = socket.getOutputStream();
		InputStream in = socket.getInputStream();
		
		//out be used to upload files
		BufferedReader read = new BufferedReader(new FileReader(".\\src\\blog7\\青春.txt"));
		PrintWriter writer = new PrintWriter(out,true);
		String line;
		while( (line=read.readLine()) != null ){
			writer.write(line);
		}
		
		read.close();
		socket.shutdownOutput();
		
		//in be used to receive information from Server
		BufferedReader bin = new BufferedReader(new InputStreamReader(in));
		String str;
		str = bin.readLine();
		System.out.println(str);//打印服务器回执的信息
		socket.close();
	}
}

class MyServer implements Runnable{ //并不是真的服务器,而是通过传递进来的Socket进行的服务器的业务处理类

	private Socket socket;
	
	public MyServer(Socket s) {
		super();
		socket = s;
	}
	
	@Override
	public void run() {
		String ip = socket.getInetAddress().getHostAddress();
		System.out.println(ip + "...connected..");
		int count = 0; // used to check file whether is repeated.
		
		try {
			BufferedReader read = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			File file = new File("FileFromClient" + count + ".txt");
			while(file.exists()){
				file = new File("FileFromClient" + (++count) + ".txt");				
			}
			PrintWriter write = new PrintWriter(new FileWriter(file));
			String line;
			while( (line=read.readLine()) != null ){
				System.out.println(line);
			}
			
			//upload completed,send a massage
			BufferedWriter send = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
			send.write("上传成功啦...");
			send.flush();
			
			write.close();
			socket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}


 

5、UDP编程技术

DatagramPacket类:将数据打包,即创建一个对象,称为数据包。

DatagramSocket类:用来发送和接收数据包的套接字,负责将打包好的数据包发送到目的地,或从目的地接收数据包。

例如:发送“你好”两字到主机“www.baidu.com,端口2016,步骤如下

byte[] buffer = “你好”.getByte();

InetAddress destAdd = InetAddress.getByName(“www.baidu.com”);

//打包IP地址、端口、数据、长度,成一个数据包对象

DatagramPacket dataPacket = new DatagramPacket(buff,buff.length,destAdd,2016);

DatagramSocket sendSocket = new DatagramSocket();

sendSocket.senddataPacket);//用套接字发送已打包好的数据对象。

 

又例如,接收外界发送到本机2016号端口的数据包,步骤如下:

byte[] buff = new byte[8192];

//将这个缓冲区绑定给数据包

DatagramPacket recPacket = new DatagramPacket(buff,buff.length);

//本机IP,指定端口2016建立Socket

DatagramSocket recSocket = new DatagramSocket(2016);

//通过套接字接收到一个数据包放到recPacket空包缓冲中

recSocket.receive(recPacket);

//获取接收到的数据包的长度

Int length = recPacket.getLength();

//获取接收到的数据包的内容getData

String msg = new String(recPacket.getData(),0,length);

System.out.println(msg);

 

TestUDP.javaUDP聊天程序实例)

package blog8;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/**
 * UDP服务器与客户机双向通信实例
 */
public class TestUDP {
	
	public static void main(String[] args) throws SocketException {
		DatagramSocket send = new DatagramSocket();
		DatagramSocket rece = new DatagramSocket(6666);
		new Thread(new Send(send)).start();
		new Thread(new Rec(rece)).start();
	}
}

//客户机:发送端
class Send implements Runnable{

	private DatagramSocket ds;

	public Send(DatagramSocket ds) {
		super();
		this.ds = ds;
	}
	
	@Override
	public void run() {
		BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
		String line;
		try {
			while( (line=read.readLine()) != null ){
				byte [] buffer = line.getBytes();
				//打包数据
				DatagramPacket dp = new DatagramPacket(buffer,buffer.length,
						InetAddress.getByName("localhost"),6666);
				ds.send(dp);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}

//服务器,接收端
class Rec implements Runnable{

	private DatagramSocket socket;
	
	public Rec(DatagramSocket socket) {
		super();
		this.socket = socket;
	}
	
	@Override
	public void run() {
		while(true){
			byte [] buffer = new byte[1024];
			DatagramPacket dp = new DatagramPacket(buffer,0,buffer.length);//空包用来存放接收的数据包
			try {
				socket.receive(dp);
			} catch (IOException e) {
				e.printStackTrace();
			}
			String ip = dp.getAddress().getHostAddress();
			String data = new String( dp.getData(),0,dp.getLength());
			System.out.println(ip + "  " + data );
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值