CHAPTER-15 网络编程

网络编程



IP地址

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

网络地址:表示计算机或网络设备所在的网段

主机地址:表示特定主机或网络设备

在这里插入图片描述

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

查看本机的IP地址
ipconfig

测试网络是否畅通

ping 目标IP地址

DNS:Domain Name System,域名系统。用于域名与IP地址的相互转换

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

B/S:Browser/Server:浏览器/服务器模式

C/S:Client/Server,客户端/服务器模式

网络通信协议

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

在这里插入图片描述

TCP/IP五层

物理层

数据链路层

网络层

传输层

应用层

Socket

Socket:通信链路的端点就被称为"套接字"(英文名Socket)

分类

流式套接字(SOCK_STREAM)

面向连接、可靠的数据传输服务

数据报式套接字(SOCK_DGRAM)

无连接服务

原始套接字(SOCK_RAW)

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

java.net包

Socket

ServerSocket

DatagramPacket

DatagramSocket

InteAddress

基于TCP协议的Socket网络通信

用来实现双向安全连接网络通信

Socket通信模型

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

在这里插入图片描述

Socket网络编程步骤

STEP 1:建立连接:网络编程模型:客户端/服务器(C/S)

STEP 2:打开Socket关联的输入输出流

STEP 3:数据流中读写信息

STEP 4:关闭所有的数据流和Socket

传递字符串

Socket编程关键实现

1.ServerSocket、Socket对象创建

2.ServerSocket.accept()监听接受请求,建立连接

3.输入输出流创建

传递对象

网络通信中对象的的传递借助序列化实现
ObjectOutputStream oos = new ObjectOutputStream(...);
oos.writeObject(...);

ObjectInputStream ois = new ObjectInputStream(...);
Object = ois.readObject();

实现多客户请求

1.采用多线程的方式

2.一个专门负责监听的应用主服务程序

3.一个专门负责处理请求的线程程序

多客户端与服务器网络通信,可借助多线程实现

客户端

发送请求,接收响应

服务器

循环监听用户请求

一旦监听到请求,创建并开启线程

线程

接收并处理客户请求

获取客户端IP信息

java.net.InetAddress

getHostAddress():返回文本显示的IP地址字符串

getHostName():获取此IP地址的主机名



案例

案例一

模拟用户登录的功能

实现客户发送登陆用户信息,服务器端显示登陆信并响应给客户端登陆成功

-测试类

package hw1;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Test {
	public static void main(String[] args) {
		
		try {
			Socket socket = new Socket("localhost",8888);
			OutputStream os = socket.getOutputStream();
			ObjectOutputStream oos = new ObjectOutputStream(os);
			User user = new User("admin","123456");
			oos.writeObject(user);
			
			//String showInfo = "用户名:  admin;密码:123456";
			//os.write(showInfo.getBytes());
			socket.shutdownOutput();
			InputStream is =socket.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String reply;
			while((reply = br.readLine())!=null) {
				System.out.println("服务器响应:  "+reply);
			}
			
			br.close();
			is.close();
			oos.close();
			os.close();
			socket.close();
			
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

-User类

package hw1;

import java.io.Serializable;

public class User implements Serializable{
	private String userName;
	private String userPwd;
	public User() {
		super();
		// TODO Auto-generated constructor stub
	}
	public User(String userName, String userPwd) {
		super();
		this.userName = userName;
		this.userPwd = userPwd;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getUserPwd() {
		return userPwd;
	}
	public void setUserPwd(String userPwd) {
		this.userPwd = userPwd;
	}
}

-线程类

package hw1;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;


/**
 * 服务器
 * @author admin
 *
 */
public class LoginServer {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			ServerSocket serverSocket = new ServerSocket(8888);
			Socket socket = serverSocket.accept();
			InputStream is = socket.getInputStream();
			ObjectInputStream ois = new ObjectInputStream(is);
			User user = (User)ois.readObject();
			System.out.println("客户端:  "+user.getUserName()+"-"+user.getUserPwd());
			OutputStream os = socket.getOutputStream();
			
//			String info;
//			while((info = br.readLine())!= null) {
//				System.out.println("客户端:  "+info);
//			}
			
			String reply = "欢迎登陆";
			os.write(reply.getBytes());
			
			os.close();
			ois.close();
			is.close();
			socket.close();
			serverSocket.close();
		
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

案例二

需求说明:升级前一个上机内容,实现多客户端用户登录

分析:

1.创建服务器端线程类,run()方法中实现对一个请求的相应处理

2.修改服务器端代码,实现循环监听状态

3.服务器端没见听到一个请求,创建一个处理线程

-线程类

package homework2;
/**
 * 服务器端的线程类
 */
import java.io.*;
import java.net.*;

public class LoginThread extends Thread{
	private Socket socket;	//端口作为属性,便于每个线程根据接收到的客户端端口来操作run()方法
	
	
	public LoginThread(Socket socket) {
		this.socket = socket;
	}


	@Override
	public void run() {
		InputStream is =null;
		InputStreamReader isr =null;
		ObjectInputStream ois=null;
		OutputStream os =null;
		Writer osw =null;
		try {
			//创建对应客户端socket的输入流,返回InputStream类型
			is = socket.getInputStream();
			//ObjectInputStream需要一个Reader类型参数,
			//而InputStreamReader刚好能连接上is(对接客户端)
			isr = new InputStreamReader(is);
			//用ObjectInputStream来接收对象数据
			 ois =new ObjectInputStream(is);
			//把读到的对象赋给新的变量user
			 User user =(User)ois.readObject();
			//获得客户端对应的socket的输出流,给客户端反馈信息,返回OutputStream类型
			 os=socket.getOutputStream();
			//用字符输出流输出信息给客户端
			 osw=new OutputStreamWriter(os); 
			//判断客户端输入的用户名密码是否正确
			 if(user.getName().equals("admin")&&user.getPwd().equals("123456")) {
				//正确,反馈登陆成功给客户端
				 osw.write("登录成功!");
			 }else {
				//错误,反馈登录失败给客户端
				 osw.write("用户名或密码不正确!");
			 }
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}finally {
			try {
				if(osw!=null) {
					osw.close();
				}
				if(os!=null) {
					os.close();
				}
				if(ois!=null) {
					ois.close();
				}
				if(isr!=null) {
					isr.close();
				}
				if(is!=null) {
					is.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
	}	
}

-服务器端

package homework2;

/**
 * 服务器端
 */
import java.io.IOException;
import java.net.*;

public class servers {

	public static void main(String[] args) {
		ServerSocket serverSocket=null;
		Socket socket=null;
		try {
			//创建服务器端口的对象,端口号8888,与客户端端口号对应
			serverSocket =new ServerSocket(8888);
			//死循环,让服务器能一直监听客户端发送信息,不需要每次都重新运行服务器
			while(true) {
				//等待接收每一个客户端发来的信息,返回一个和客户端对应的socket
				socket =serverSocket.accept();
				//每接收到一个客户端的信息,创建一个线程来处理对应客户端,
				//把对应客户端的端口socket传到对应线程对象的socket属性中去,在线程类的run()中用
				LoginThread thread =new LoginThread(socket);
				//运行线程
				thread.start();
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				if(socket!=null) {
					socket.close();
				}
				if(serverSocket!=null) {
					serverSocket.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

-Socket

package homework2;

/**
 * 客户端
 */
import java.io.*;
import java.net.*;
import java.util.*;

public class Sockets {
	public static void main(String[] args) {
		Scanner scan =new Scanner(System.in);
		Socket socket=null;
		OutputStream os =null;
		ObjectOutputStream oos=null;
		InputStream is  =null;
		InputStreamReader isr=null;
		BufferedReader br =null;
		try {
			//创建客户端连接服务器的端口对象socket  端口号8888
			socket =new Socket("localhost",8888);
			//获得客户端端口的输出流对象(返回值是OutputStream类型)
			os =socket.getOutputStream();
			//创建一个User对象,用来存一组用户名密码信息
			User user =new User();
			System.out.print("请输入用户名:");
			user.setName(scan.next());
			System.out.print("请输入密码:");
			user.setPwd(scan.next());
			//输出对象数据的输出流对象(序列化)ObjectOutputStream类型
			oos=new ObjectOutputStream(os);
			//用序列化把user对象输出到服务器
			oos.writeObject(user);
			//关闭客户端端口的输出流,不然后面读不到服务器的反馈
			socket.shutdownOutput();
			//获得端口的输入流对象,用来读取服务器反馈信息,返回InputStream类型
			is =socket.getInputStream();
			//创建字符输入流对象
			isr =new InputStreamReader(is);
			//用能整行读取的BufferReader输入流
			 br =new BufferedReader(isr);
			//读服务器反馈的信息
			System.out.println(br.readLine());
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				if(br!=null) {
					br.close();
				}
				if(isr!=null) {
					isr.close();
				}
				if(is!=null) {
					is.close();
				}
				if(oos!=null) {
					oos.close();
				}
				if(os!=null) {
					os.close();
				}
				if(socket!=null) {
					socket.close();
				}
	
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
	}
}

-User

package homework2;
/**
 * 登录账号信息类
 */
import java.io.Serializable;

public class User implements Serializable{
	private String name;	//用户名
	private String pwd;		//密码
	
	
	public User() {
	}

	public User(String name, String pwd) {
		this.name = name;
		this.pwd = pwd;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
}

{
e.printStackTrace();
}

	}
}

}


-User

```JAVA
package homework2;
/**
 * 登录账号信息类
 */
import java.io.Serializable;

public class User implements Serializable{
	private String name;	//用户名
	private String pwd;		//密码
	
	
	public User() {
	}

	public User(String name, String pwd) {
		this.name = name;
		this.pwd = pwd;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值