1 网络概括
1.1 网页编程与网络编程
- 网页编程 : 注重的是上层的应用
- 网络编程 : 注重是底层数据的传输
1.2 了解
- IP : 定义节点
- 端口 : 区分软件
- URL : 统一资源定位符
- 协议 : 标准,规范,规则,合同
- 传输层协议 : 互联网中传输数据需要满足传输层协议,传输变的更加畅通,更安全
- UDP : 非面向连接,相当于写信, 只管写只管邮,协议简单,不安全,效率高 大小限制不超过60k
- TCP : 面向连接, 相当于打电话, 安全, 效率较低 ,没有大小限制 ,基于3次握手,四次挥手
1.3 重点
2 IP
2.1 理解
- IP : 定义节点,区分节点(互联网中的电子设备都可以通过IP定义)
分类: IPV4 ->4个字节->32位 IPV6 ->128位
192.168.0.0~192.168.255.255 非注册IP,供组织内部使用的IP
127.0.0.1 ->本地IP
localhost ->本地域名
IP->域名 : DNS服务器 - java.net网络包
InetAddress : 表示IP地址
2.2 代码
public class Class001_IP {
public static void main(String[] args) throws UnknownHostException {
InetAddress ip1 = InetAddress.getLocalHost();
System.out.println(ip1);
System.out.println(ip1.getHostAddress());
System.out.println(ip1.getHostName());
InetAddress ip2 = InetAddress.getByName("www.baidu.com");
System.out.println(ip2);
System.out.println(ip2.getHostAddress());
System.out.println(ip2.getHostName());
}
}
3 端口
3.1 理解
- 端口 : port
区分软件 - 0~65535表示端口号 2个字节
- 统一协议下端口号不能冲突
- 8000以下端口不建议使用,预留端口号
- 常见的端口号:
80 : http
8080 : tomcat
1521 : Oracle
3306 : Mysql - InetSocketAddress 此类实现IP套接字地址(IP地址+端口号)
3.2 代码
public class Class002_Port {
public static void main(String[] args){
InetSocketAddress address = new InetSocketAddress("127.0.0.1",9999);
System.out.println(address);
System.out.println(address.getAddress().getHostAddress());
System.out.println(address.getPort());
}
}
4 URL
4.1 理解
- URL : 统一资源定位符,向万维网上的“资源”的指针。
互联网的三大基石 : URL HTML HTTP
4.2 组成
- URL组成:
1.协议 http
2.域名 www.baidu.com
3.端口 80
4.资源 index.html
5.数据 username=zhangsan&password=123
6.锚点 #a
4.3 练习
- url : http://www.baidu.com:80/index.html?username=zhangsan&password=123#a
4.4 代码
public class Class003_URL {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("http://www.baidu.com:80/index.html?username=zhangsan&password=123#a");
System.out.println(url);
System.out.println("协议:"+url.getProtocol());
System.out.println("域名:"+url.getHost());
System.out.println("端口:"+url.getPort());
System.out.println("资源:"+url.getFile());
System.out.println("文件路径"+url.getPath());
System.out.println("数据:"+url.getQuery());
System.out.println("锚点:"+url.getRef());
}
}
5 UDP
5.1 Socket 套接字
- 是传输层为应用层开辟的一个小口子,相当于码头,插座
- 不同协议下Socket实现不同
- 网络编程确实是面向Socket编程
5.2 UDP
- DatagramPacket 数据报包
- DatagramSocket 此类表示用于发送和接收数据报包的套接字。
- UDP协议下两端(发送端,接收端)是平等,数据基于包裹,基于字节数组
5.3 UDP协议实现基础的发送端
- 定义我是发送端 DatagramSocket(int port) 构造一个数据报套接字并将其绑定到本地主机上的指定端口。
- 准备数据
- 数据打包
- 发送端发送包裹 void send(DatagramPacket p) 从此套接字发送数据报包。
- 关闭
5.4 UDP协议实现基础的接收端
- 定义我是接收端
- 准备包裹用来接收数据
- 接收端接收数据
- 处理数据
- 关闭
5.5 代码
5.5.1 发送端
public class Class001_Send {
public static void main(String[] args) throws IOException {
System.out.println("-----------------发送端---------------------");
DatagramSocket sendSocket = new DatagramSocket(9999);
byte[] arr = "你好".getBytes();
DatagramPacket packet = new DatagramPacket(arr,0,arr.length,new InetSocketAddress("localhost",9898));
sendSocket.send(packet);
sendSocket.close();
}
}
5.5.2 接收端
public class Class002_Receive {
public static void main(String[] args) throws IOException {
System.out.println("-----------------接收端---------------------");
DatagramSocket receiveSocket = new DatagramSocket(9898);
byte[] arr = new byte[1024];
DatagramPacket packet = new DatagramPacket(arr,0,arr.length);
receiveSocket.receive(packet);
byte[] result = packet.getData();
int len = packet.getLength();
System.out.println(new String(result,0,len));
receiveSocket.close();
}
}
6 TCP
6.1 理解
6.2 发送与接收
6.2.1 tcp协议实现客户端 : 基本流程
- 构建我是客户端 Socket(String host, int port) IP+端口号指要连接的服务器的IP与端口
- 基于IO操作
- 关闭
6.2.2 tcp协议实现服务端 : 基本流程
- 构建我是服务端 ServerSocket(int port)
- 阻塞式监听 Socket accept() 侦听对此套接字的连接并接受它。
- IO操作
- 关闭
6.3 代码
6.3.1 发送端
public class Class001_Client {
public static void main(String[] args) throws IOException {
System.out.println("----我是客户端---------");
Socket client = new Socket("127.0.0.1", 8989);
DataOutputStream os = new DataOutputStream(client.getOutputStream());
os.writeUTF("哈哈");
os.flush();
os.close();
client.close();
}
}
6.3.2 接收端
public class Class002_Server {
public static void main(String[] args) throws IOException {
System.out.println("----我是服务端---------");
ServerSocket server = new ServerSocket(8989);
Socket client = server.accept();
System.out.println("----一个客户端连接成功---------");
DataInputStream is = new DataInputStream(client.getInputStream());
String str = is.readUTF();
System.out.println(str);
is.close();
client.close();
server.close();
}
}
7 用户登录练习
7.1 单用户登录
7.1.1 客户端
- 构建我是客户端
- 键盘接收用户名与密码
- 基于IO操作向服务器发送数据
- 关闭
public class Class003_LoginClient {
public static void main(String[] args) throws IOException {
System.out.println("----我是客户端---------");
Socket client = new Socket("127.0.0.1", 8989);
BufferedReader rd = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入用户名 : ");
String username = rd.readLine();
System.out.println("请输入用户密码 : ");
String password = rd.readLine();
DataOutputStream os = new DataOutputStream(client.getOutputStream());
os.writeUTF("username="+username+"&password="+password);
os.flush();
os.close();
rd.close();
client.close();
}
}
7.1.2 服务端
- 构建我是服务端
- 阻塞式监听
- IO操作接收客户端数据
1)获取输入流
2)读入数据
3)处理数据
4)关闭 - 关闭
public class Class004_LoginServer {
public static void main(String[] args) throws IOException {
System.out.println("----我是服务端---------");
ServerSocket server = new ServerSocket(8989);
Socket client = server.accept();
System.out.println("----一个客户端连接成功---------");
DataInputStream is = new DataInputStream(client.getInputStream());
String str = is.readUTF();
String uname = "";
String upwd = "";
String[] arr = str.split("&");
for(String s:arr){
String[] arr2 = s.split("=");
if("username".equals(arr2[0])){
uname = arr2[1];
}else if("password".equals(arr2[0])){
upwd = arr2[1];
}
}
if("laopei".equals(uname) && "1234".equals(upwd)){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
is.close();
client.close();
server.close();
}
}
7.2 双向登录
7.2.1 客户端
- 构建我是客户端
- 键盘接收用户名与密码
- 基于IO操作向服务器发送数据
- 基于IO操作接收服务器响应的结果
- 处理结果
- 关闭
public class Class005_LoginTwoWayClient {
public static void main(String[] args) throws IOException {
System.out.println("----我是客户端---------");
Socket client = new Socket("127.0.0.1", 8989);
BufferedReader rd = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入用户名 : ");
String username = rd.readLine();
System.out.println("请输入用户密码 : ");
String password = rd.readLine();
DataOutputStream os = new DataOutputStream(client.getOutputStream());
os.writeUTF("username="+username+"&password="+password);
os.flush();
DataInputStream is = new DataInputStream(client.getInputStream());
String result = is.readUTF();
System.out.println(result);
is.close();
os.close();
rd.close();
client.close();
}
}
7.2.2 服务端
- 构建我是服务端
- 阻塞式监听
- IO操作接收客户端数据
- 处理数据
- IO操作将结果响应给客户端
- 关闭
public class Class006_LoginTwoWayServer {
public static void main(String[] args) throws IOException {
System.out.println("----我是服务端---------");
ServerSocket server = new ServerSocket(8989);
Socket client = server.accept();
System.out.println("----一个客户端连接成功---------");
DataInputStream is = new DataInputStream(client.getInputStream());
String str = is.readUTF();
String uname = "";
String upwd = "";
String[] arr = str.split("&");
for(String s:arr){
String[] arr2 = s.split("=");
if("username".equals(arr2[0])){
uname = arr2[1];
}else if("password".equals(arr2[0])){
upwd = arr2[1];
}
}
DataOutputStream os = new DataOutputStream(client.getOutputStream());
if("laopei".equals(uname) && "1234".equals(upwd)){
os.writeUTF("登录成功");
}else{
os.writeUTF("登录失败");
}
os.flush();
os.close();
is.close();
client.close();
server.close();
}
}
7.3 多用户登录服务器端
7.3.1 循环实现
- 通过循环实现,可以实现允许多个客户端访问,可以对多个客户端响应
- 但是排序访问
public class Class007_MulLoginTwoWayServer {
public static void main(String[] args) throws IOException {
System.out.println("----我是服务端---------");
ServerSocket server = new ServerSocket(8989);
boolean flag = true;
while(flag){
Socket client = server.accept();
System.out.println("----一个客户端连接成功---------");
DataInputStream is = new DataInputStream(client.getInputStream());
String str = is.readUTF();
String uname = "";
String upwd = "";
String[] arr = str.split("&");
for(String s:arr){
String[] arr2 = s.split("=");
if("username".equals(arr2[0])){
uname = arr2[1];
}else if("password".equals(arr2[0])){
upwd = arr2[1];
}
}
DataOutputStream os = new DataOutputStream(client.getOutputStream());
if("laopei".equals(uname) && "1234".equals(upwd)){
os.writeUTF("登录成功");
}else{
os.writeUTF("登录失败");
}
os.flush();
os.close();
is.close();
client.close();
}
server.close();
}
}
7.3.2 通过多线程实现
public class Class008_MulLoginTwoWayServer {
public static void main(String[] args) throws IOException {
System.out.println("----我是服务端---------");
ServerSocket server = new ServerSocket(8989);
boolean flag = true;
while(flag){
Socket client = server.accept();
System.out.println("----一个客户端连接成功---------");
new Thread(new Channel(client)).start();
}
server.close();
}
static class Channel implements Runnable{
private Socket client = null;
private DataInputStream is = null;
private DataOutputStream os = null;
public Channel(Socket client) {
this.client = client;
try {
is = new DataInputStream(client.getInputStream());
os = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
public String read(){
String str = "";
try {
str = is.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
public void write(String msg){
try {
os.writeUTF(msg);
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void close(){
if(os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(client!=null){
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
String str = read();
String uname = "";
String upwd = "";
String[] arr = str.split("&");
for(String s:arr){
String[] arr2 = s.split("=");
if("username".equals(arr2[0])){
uname = arr2[1];
}else if("password".equals(arr2[0])){
upwd = arr2[1];
}
}
if("laopei".equals(uname) && "1234".equals(upwd)){
write("登录成功");
}else{
write("登录失败");
}
close();
}
}
}