Java中网络编程重点总结

IP地址(Internet  Protocol):唯一标识网络上的每一台计算机

IP地址的组成:32位,由4个8位二进制数组成

二进制变成十进制方法:位数数值乘以2的位数次方,最大到255

 

IP地址 = 网络地址 +主机地址

网络地址:标识计算机或网络设备所在的网段

主机地址:标识特定主机或网络设备

IP地址的配置和检测:

查看IP地址,检测网络是否畅通

查看本机的IP地址:ipconfig

测试网络是否通畅:ping (再加上)目标IP地址

【1. 开始里面直接输入cmd;2. 打开dos系统;3. 输入代码】

DNS域名解析:Domain Name System,域名系统

为了好访问,好记忆。通过DNS

 

网络服务器:

通常指在网络环境下,具有较高计算能力,能够提供用户服务功能的计算机

B/S:浏览器服务器端的服务程序【好处:服务器端自己升级就行了】

C/S:客户端服务器端的服务程序

 

网络通信协议:

为在网络中不同的计算机之间进行通信而建立的规则、标准或约定的集合

【数据在网络中传输是很复杂的】

HTTP协议:超文本传输协议,互联网应用最广泛的。

FTP协议:文件传输协议。

SMTP协议:简单邮件传输协议。

TCP协议(Transmission Control Protocol 传输控制协议):面向连接的、可靠的、基于字节流的传输通信协议。

UDP协议(User Datagram Protocol 用户数据报协议):无连接的协议,在传输数据之前,客户端和服务器并不建立和维护连接,效率很快。

 

Socket:

通信链路的端点就被称为“套接字”(英文名Socket);是提供给应用程序的接口

【Socket的底层机制复杂,Java平台提供了一些简单的API,可以更简单有效的使用Socket开发而无需了解底层机制】

Socket分类

  1. 流式套接字(SOCK_ STREAM)【面向连接、可靠的数据传输服务(对应服务是TCP链接)】
  2. 数据报式套接字(SOCK_ DGRAM)【无连接服务(数据报似的,基于UDP)更高效】
  3. 原始式套接字(SOCK_ RAW)

 

java.net包:

Socket

ServerSocket

DatagramPacket

DatagramSocket

InetAddress

……

基于TCP协议的Socket网络通信:用来实现双向安全连接网络通信

Socket通信模型:进行网络通信时,Socket需要借助数据流来完成数据的传递工作

                  C:客户端                                                           S:服务器

Socket网络编程一般可以分成如下步骤进行:

Servicer

Client

1. 创建ServerSocket(…)对象,绑定某一哥端口号

1. 创建Socket("…",…)要指定服务器的IP地址,也要指定端口号

2. 通过accept()侦听方法,阻塞,等待对方连接

 发送请求并被accept()侦听到,并建立           连接

3. 通过输入、输出流传递信息【客户端是输出输入,服务器是输入输出】

4. 关闭释放资源

例1【直接传参数的方法】:

服务器端程序:

public class LogicServicer {
	public static void main(String[] args) {
		try {
			//接收客户端请求
			//创建一个Socket
			ServerSocket serverSocket = new ServerSocket(5000);
			//使用accept()侦听并接收到此ServerSocket的连接
			Socket socket = serverSocket.accept();//侦听到之前都是阻塞的
			//获得输入流,获得用户的请求
			//数据流输入
			InputStream is = socket.getInputStream();
			// BufferedReader读取字符流
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String info;
			// BufferedReader的方法可以一行一行的读
			while((info = br.readLine())!=null){
				System.out.println("客户端:"+info);
			}
			//给客户端一个响应
			String reply = "欢迎登陆";
			//通过输出流将响应发送回给客户端
			OutputStream os = socket.getOutputStream();
			os.write(reply.getBytes());	
			//释放相应资源
			os.close();
			br.close();
			is.close();
			socket.close();
			serverSocket.close();
		} catch (IOException e) {
			e.printStackTrace();
		} } }

客户端程序:

public class LogicClient {
	public static void main(String[] args) {
		//创建一个客户端的Socket
		try {
			Socket socket = new Socket("localhost",5000);
			//通过输出流发送请求
			//直接输出数据流
			String info = "用户名:樱桃小丸子;密码:123456";
			OutputStream os = socket.getOutputStream();
			//打散成数据数组
			byte[] infos = info.getBytes();
			os.write(infos);
			//关闭输出流,这是一个半关闭
			socket.shutdownOutput();
			//通过输入流接收服务器给我的响应
			InputStream is = socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String reply;
			while((reply = br.readLine())!=null){
				System.out.println("服务器:"+reply);
			}
			//释放资源
			os.close();
			socket.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} } }

测试结果:

例2【通过用户对象传参数的方法】:

用户类程序:

public class User implements Serializable{
	private String userName;
	private String pwd;
	public User() {}
	public User(String userName, String pwd) {
		this.userName = userName;
		this.pwd = pwd;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	} }

服务器端程序:

public class LogicServicer {
		public static void main(String[] args) {
			try {
				//接收客户端请求
				//创建一个Socket
				ServerSocket serverSocket = new ServerSocket(5000);
				//使用accept()侦听并接收到此ServerSocket的连接
				Socket socket = serverSocket.accept();//侦听到之前都是阻塞的
				//获得输入流,获得用户的请求
				//将对象反序列化变成输入流
				InputStream is = socket.getInputStream();
				ObjectInputStream ois = new ObjectInputStream(is);
				User user = (User)ois.readObject();
				System.out.println("客户端:"+user.getUserName()+"-"+user.getPwd());
				//给客户端一个响应
				String reply = "欢迎登陆";
				//通过输出流将响应发送回给客户端
				OutputStream os = socket.getOutputStream();
				os.write(reply.getBytes());	
				//释放相应资源
				ois.close();
				os.close();
				is.close();
				socket.close();
				serverSocket.close();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} } } 

客户端类:

public class LogicClient {
	public static void main(String[] args) {
		//创建一个客户端的Socket
		try {
			Socket socket = new Socket("localhost",5000);
			//通过输出流发送请求
			//将对象序列化变成输出流
			User user = new User("樱桃小丸子","123456");
			OutputStream os = socket.getOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(os);
			oos.writeObject(user);
			//关闭输出流,这是一个半关闭
			socket.shutdownOutput();
			//通过输入流接收服务器给我的响应
			InputStream is = socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String reply;
			while((reply = br.readLine())!=null){
				System.out.println("服务器:"+reply);
			}
			//释放资源
			os.close();
			oos.close();
			socket.close();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} } }

测试结果:

如何实现多客户请求呢?

  1. 采用多线程的方式
  2. 一个专门负责监听的应用主服务程序
  3. 一个专门负责处理请求的线程程序

例题:

实现服务器和客户端的多线程连接;并且服务器和客户端可以无限对话。

实现思路:

服务器:

一直监听客户请求

一旦监听到有客户请求,立即创建一个线程,开启线程

线程:

接收客户请求,基于客户一个响应(这是之前服务器要做的事)

线程构造方法中去绑定客户端的Socket

客户端:

发送请求到服务器

接收服务器的响应

例如:

线程类:

//接收客户请求,基于客户一个响应(这是之前服务器要做的事)
//线程构造方法中去绑定客户端的Socket
public class LogicThread extends Thread {
	private Socket socket;
	public LogicThread(Socket socket){
		this.socket=socket;
	}
	//接收客户请求,基于客户一个响应
	public void run(){
		InputStream is=null;
		BufferedReader br=null;
		PrintWriter pw=null;
		OutputStream os=null;
		try{
			Scanner input = new Scanner(System.in);
			//获得输入流,获得用户的请求
			while(true){
				is= socket.getInputStream();
				br = new BufferedReader(new InputStreamReader(is));
				System.out.println(socket.getInetAddress()+"说"+br.readLine());
				//给客户端一个响应
				//通过输出流将响应发送回给客户端
				String reply =input.next();
				os = socket.getOutputStream();
				pw = new PrintWriter(os);
				pw.println(reply);
				pw.flush();
			}
			//释放相应资源
		}catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				pw.close();
				os.close();
				br.close();
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			} } } }

服务器程序:

//一直监听客户请求
//一旦监听到有客户请求,立即创建一个线程,开启线程
public class LogicServicer {
	public static void main(String[] args) {
		try {
			//接收客户端请求
			//创建一个Socket
			ServerSocket serverSocket = new ServerSocket(8848);
			System.out.println("启动服务器");
			//使用accept()侦听并接收到此ServerSocket的连接
			//一直监听客户请求
			while(true){
				Socket socket = serverSocket.accept();//侦听到之前都是阻塞的
				System.out.println("已连接");
				//创建一个和该客户端响应的线程
				LogicThread logicThread = new LogicThread(socket);
				logicThread.start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} } }

客户端类:

//发送请求到服务器
//接收服务器的响应
public class LogicClient {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		OutputStream os=null;
		PrintWriter pw=null;
		InputStream is=null;
		BufferedReader br=null;
		//创建一个客户端的Socket
		try {
			Socket socket = new Socket("localhost",8848);
			System.out.println("客户端已启动");
			//通过输出流发送请求
			while(true){
			String info =input.next();
			os = socket.getOutputStream();
			pw = new PrintWriter(os);
			pw.println(info);
			pw.flush();
			//通过输入流接收服务器给我的响应
			is = socket.getInputStream();
			br = new BufferedReader(new InputStreamReader(is));
			System.out.println("服务器:"+br.readLine());
			}
			//释放资源
			} catch (UnknownHostException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}finally{
				try {
					os.close();
					pw.close();
					br.close();
					is.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} } } }

测试结果:

如何获得客户的IP?

InetAddress(IP地址的封装)

应用实例:

InetAddress ia = socket.getInetAddress();

String ip= ia.getHostAddress();

 

基于UDP协议的Socket编程:

 

TCP

UDP

是否连接

面向连接

面向非连接

传输可靠性

可靠

不可靠

速度

 

基于UDP协议的Socket网络编程步骤

  1. 利用 DatagramPacket 对象封装数据报
  2. 利用 DatagramSocket 发送数据报
  3. 利用 DatagramSocket 接收数据报
  4. 利用 DatagramPacket 处理数据报

DatagramPacket类

封装了数据报的数据、数据长度、目标地址和目标端口

DatagramSocket类

接收和发送DatagramPacket对象封装好的数据报

【两个类都在java.net包里】

例子:

礼物—数据(字符串)

包裹—DatagramPacket

快递点—DatagramSocket

寄礼物—send()

收礼物—receive()

基于UDP的Socket通信,服务端:

public class LogicServicer {
	public static void main(String[] args) {	
		byte[] infos = new byte[1024];
		DatagramPacket dp = new DatagramPacket(infos,infos.length);
		//快递点
		DatagramSocket socket=null;
		try {
			socket = new DatagramSocket(5000);
			//在快递点取礼物
			socket.receive(dp);
			//拆礼物
			String info = new String(dp.getData(),0,dp.getData().length);
			System.out.println("客户端说:"+info);	
			//给客户端一个响应
			String reply ="一件羽绒服";
			byte[] reply2 = reply.getBytes();
			//客户端地址
			SocketAddress sa = dp.getSocketAddress();
			//打开一个包裹
			DatagramPacket dp1 = new DatagramPacket(reply2,reply2.length,sa);
			//寄出去
			socket.send(dp1);	
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			socket.close();
		} } }

基于UDP的Socket通信,客户端:

public class LogicClient {
	public static void main(String[] args) {
		//买礼物
		String info="心形巧克力!";
		byte[] infos = info.getBytes();
		//对方地址和邮编(端口号)
		InetAddress ia;
		//快递点
		DatagramSocket socket = null; 
		try {
			ia = InetAddress.getByName("localhost");
			//包裹包装礼物
			DatagramPacket dp = new DatagramPacket(infos, infos.length, ia, 5000);
			socket = new DatagramSocket();
			//通过快递点往外寄出礼物
			try {
				socket.send(dp);
			} catch (IOException e) {
				e.printStackTrace();
			}
			//接收服务器的响应
			byte[] replys = new byte[1024];
			DatagramPacket dp1 = new DatagramPacket(replys,replys.length);
			socket.receive(dp1);
			String reply = new String(dp1.getData(),0,dp.getData().length);
			System.out.println("服务器的响应:"+reply);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			socket.close();
		} } }

测试结果:

猜你喜欢

转载自blog.csdn.net/baidu_29343517/article/details/81490769
今日推荐