2017年4月19号课堂笔记

2017年4月19号   小雨  空气质量:轻度污染

内容:基于TCP协议的socket网络编程,基于TCP协议的socket网络编程(单用户、多用户登陆)

基于UDP协议的socket网络编程,U1项目思路讲解

一、Socket网络编程步骤

(一)基于TCP协议的socket网络编程的步骤

01.建立连接
02.打开socket关联的输入输出流
03.数据流中读写数据
04.关闭所有数据流和socket

Socket 客户端C
ServerSocket 服务器S
C/S架构

(二)基于UDP协议的socket网络编程的步骤

01.利用DatagramPacket对象封装数据报
02.利用DatagramSocket发送数据报
03.利用DatagramSocket接收数据报
04.利用DatagramPacket对象处理数据报


DatagramPacket: 打包,拆包!
是封装了数据报的数据,数据的长度,目标地址和目标端口!

DatagramSocket: 接收,发送!
接收和发送封装好的数据报!

(三)TCP 和 UDP的区别

01. 是否面向连接
TCP面向连接! UDP面向非连接!
02.传输的可靠性
TCP安全可靠! UDP不可靠!
03.传输的速度
TCP慢! UDP快!

二、基于TCP协议的socket网络编程(超市购物案例)

老师代码:

1)服务器 (超市)ServerSocket

package cn.bdqn.supermarket;

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

/**
* 服务器 (超市)ServerSocket
*
*/
public class ServerSocketTest {

public static void main(String[] args) {
ServerSocket serverSocket = null; // 超市
Socket socket = null; // 顾客
InputStream stream = null; // 购物车
BufferedReader br = null; // 收银员
OutputStream os = null; // 服务员的回应语句
try {
// 在指定的位置开了一家超市
serverSocket = new ServerSocket(8800);
// 超市开门 等待顾客上门
socket = serverSocket.accept();
// 顾客开始购物 把东西 放进 购物车 内 输入流
stream = socket.getInputStream();
/**
* 结账?
* 01.需要 把购物车的东西 放到 收银台上 ===》商品的暂存处
* 02.收银员 需要扫码 一次一个商品
*/
br = new BufferedReader(new InputStreamReader(stream));
String info = null;
while ((info = br.readLine()) != null) { // 说明购物车还有商品
System.out.println("顾客购买的商品是:" + info);
}
// 顾客结账完毕 准备带回
socket.shutdownInput(); // 顾客没有离开超市 只是不购物!
// 接收服务员的语句
os = socket.getOutputStream();
os.write("谢谢光临".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 关闭所有资源
os.close();
br.close();
stream.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}

}

}

}

2)客户端(顾客) Socket

package cn.bdqn.supermarket;

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

/**
* 客户端(顾客) Socket
*
*/
public class SocketTest {

public static void main(String[] args) {
Socket socket = null; // 顾客
OutputStream os = null; // 钱包
InputStream is = null; // 收银员的语句
BufferedReader br = null;
try {
// 顾客 去指定的超时 购物
socket = new Socket("localhost", 8800);
// 打开钱包,疯狂购物=====》花钱 !
os = socket.getOutputStream();
// 开始购物
os.write("萨德".getBytes());
// 购物完毕
socket.shutdownOutput(); // 把钱包捂住!

// 接收我们收银员的问候
is = socket.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
String info = null;
while ((info = br.readLine()) != null) {
System.out.println("收银员说:" + info);
}

} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 关闭资源
br.close();
is.close();
os.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}

}

}

}

三、基于TCP协议的socket网络编程(多用户登陆)

老师代码:

1)用户登录需要的服务器 

package cn.bdqn.loginThread;

import java.net.ServerSocket;
import java.net.Socket;

public class ServerSocketTest {

/**
* 用户登录需要的服务器
* 需要 服务器 循环 一直 监听 登录 用户信息
* 而不是 只能监听一个用户!
*/
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;

try {
// 实例化我们的服务器
serverSocket = new ServerSocket(8800);
while (true) {
socket = serverSocket.accept(); // 在循环里 一直监听 用户登录的信息
LoginThread thread = new LoginThread(socket);
thread.start(); // 多个用户 就是 多个线程
}
} catch (Exception e) {
e.printStackTrace();
}

}

}

2)服务器监听需要的线程类

package cn.bdqn.loginThread;

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

/**
*
*服务器监听需要的线程类
*/
public class LoginThread extends Thread {
private Socket socket = null;

/**
* 每个用户都有属于自己的socket
*/
public LoginThread(Socket socket) {
this.socket = socket;
}

@Override
public void run() {
InputStream is = null;
OutputStream os = null;
/**
* 需要接收 用户这个对象!! 而不是之前的字符串!!
* 反序列化
*/
ObjectInputStream ois = null;
try {
// 打开输入和输出流 接收用户的输入 给用户一个响应
is = socket.getInputStream();
os = socket.getOutputStream();
ois = new ObjectInputStream(is);

// 获取登录用户的信息
User user = (User) ois.readObject();
System.out.println("登录用户的用户名是:" + user.getName());
System.out.println("登录用户的密码是:" + user.getPassword());
// 关闭输入流
socket.shutdownInput();

// 服务器给客户端一个成功响应
os.write("恭喜您!登录成功!".getBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 释放资源
os.close();
ois.close();
is.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

}

3)模拟登录用户的实体类

package cn.bdqn.loginThread;

import java.io.Serializable;

/**
*模拟登录用户的实体类
*/
public class User implements Serializable {

private String name; // 用户名
private String password; // 密码

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public User(String name, String password) {
super();
this.name = name;
this.password = password;
}

public User() {
super();
}

@Override
public String toString() {
return "User [name=" + name + ", password=" + password + "]";
}

}

4)真正用户的登录   客户端1

package cn.bdqn.loginThread;

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;

public class SocketTest1 {

/**
* 真正用户的登录 客户端1
*/
public static void main(String[] args) {
Socket socket = null;
InputStream is = null;
OutputStream os = null;

BufferedReader br = null; // 接收服务器的回应
/**
* 需要给服务器一个 对象 需要 序列化对象
*/
ObjectOutputStream oos = null;

try {
socket = new Socket("localhost", 8800);
// 打开输入输出流 给服务器 传递对象 接收 服务器的相应
is = socket.getInputStream();
os = socket.getOutputStream();

// 序列化
User user = new User("小黑1", "123456");
oos = new ObjectOutputStream(os);
oos.writeObject(user);
socket.shutdownOutput(); // 关闭输出流

// 接收服务器的相应
br = new BufferedReader(new InputStreamReader(is));
String info = null;
while ((info = br.readLine()) != null) {
System.out.println("服务器的响应是:" + info);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 释放资源
br.close();
oos.close();
os.close();
is.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}

}

5)真正用户的登录   客户端2

package cn.bdqn.loginThread;

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;

public class SocketTest2 {

/**
* 真正用户的登录 客户端2
*/
public static void main(String[] args) {
Socket socket = null;
InputStream is = null;
OutputStream os = null;

BufferedReader br = null; // 接收服务器的回应
/**
* 需要给服务器一个 对象 需要 序列化对象
*/
ObjectOutputStream oos = null;

try {
socket = new Socket("localhost", 8800);
// 打开输入输出流 给服务器 传递对象 接收 服务器的相应
is = socket.getInputStream();
os = socket.getOutputStream();

// 序列化
User user = new User("小黑2", "123456");
oos = new ObjectOutputStream(os);
oos.writeObject(user);
socket.shutdownOutput(); // 关闭输出流

// 接收服务器的相应
br = new BufferedReader(new InputStreamReader(is));
String info = null;
while ((info = br.readLine()) != null) {
System.out.println("服务器的响应是:" + info);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 释放资源
br.close();
oos.close();
os.close();
is.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}

}

四、基于TCP协议的socket网络编程(单用户登陆,举例现实中少有)

老师代码:

1)用户登录需要的服务器

package cn.bdqn.login;

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

public class ServerSocketTest {

/**
* 用户登录需要的服务器
*/
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
OutputStream os = null;
/**
* 需要接收 用户这个对象!! 而不是之前的字符串!!
* 反序列化
*/
ObjectInputStream ois = null;

try {
// 创建serverSocket对象
serverSocket = new ServerSocket(8800);
// 监听 用户的登录
socket = serverSocket.accept();
// 打开输入和输出流 接收用户的输入 给用户一个响应
is = socket.getInputStream();
os = socket.getOutputStream();
ois = new ObjectInputStream(is);

// 获取登录用户的信息
User user = (User) ois.readObject();
System.out.println("登录用户的用户名是:" + user.getName());
System.out.println("登录用户的密码是:" + user.getPassword());
// 关闭输入流
socket.shutdownInput();

// 服务器给客户端一个成功响应
os.write("恭喜您!登录成功!".getBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 释放资源
os.close();
ois.close();
is.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}

}

2)真正用户的登录 客户端

package cn.bdqn.login;

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;

public class SocketTest {

/**
* 真正用户的登录 客户端
*/
public static void main(String[] args) {
Socket socket = null;
InputStream is = null;
OutputStream os = null;

BufferedReader br = null; // 接收服务器的回应
/**
* 需要给服务器一个 对象 需要 序列化对象
*/
ObjectOutputStream oos = null;

try {
socket = new Socket("localhost", 8800);
// 打开输入输出流 给服务器 传递对象 接收 服务器的相应
is = socket.getInputStream();
os = socket.getOutputStream();

// 序列化
User user = new User("小黑", "123456");
oos = new ObjectOutputStream(os);
oos.writeObject(user);
socket.shutdownOutput(); // 关闭输出流

// 接收服务器的相应
br = new BufferedReader(new InputStreamReader(is));
String info = null;
while ((info = br.readLine()) != null) {
System.out.println("服务器的响应是:" + info);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 释放资源
br.close();
oos.close();
os.close();
is.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}

}

3)模拟登录用户的实体类

package cn.bdqn.login;

import java.io.Serializable;

/**
*模拟登录用户的实体类
*/
public class User implements Serializable {

private String name; // 用户名
private String password; // 密码

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public User(String name, String password) {
super();
this.name = name;
this.password = password;
}

public User() {
super();
}

@Override
public String toString() {
return "User [name=" + name + ", password=" + password + "]";
}

}

五、基于UDP协议的socket网络编程

老师代码:

1)服务器

public class Service { // 服务器
public static void main(String[] args) {
DatagramPacket dp = null; //打包 和 拆包数据
DatagramSocket ds = null; // 接收和 发送数据
//创建一个包 给客户端响应
DatagramPacket dpTo=null;
try {
byte [] buf=new byte[1024];
//创建数据包的对象
dp=new DatagramPacket(buf, buf.length);
ds=new DatagramSocket(8800);
//接收
ds.receive(dp);
//显示接收的信息 拆包
String msg=new String(dp.getData(), 0, dp.getLength());
//获取 对方的地址 客户端的信息
System.out.println(dp.getAddress().getHostAddress()+"说====:"+msg);

//回复给 客户端
byte[] reply="您好!航母已经发货!".getBytes();
// dp就是从客户端传来的信封 信封上肯定有 寄件人的地址
SocketAddress address=dp.getSocketAddress();
//打包成功
dpTo=new DatagramPacket(reply, reply.length,address);
//发送
ds.send(dpTo);
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

}

}

2)客户端:

public class Client { //客户端
public static void main(String[] args) {
DatagramPacket dp = null; //打包 和 拆包数据
DatagramSocket ds = null; // 接收和 发送数据
//创建一个包 给服务器响应
DatagramPacket dpTo=null;
InetAddress address=null;
try {
//你在网上购物 要不要给客服 说你的地址
byte[] say="买个航空母舰!".getBytes();
//获取本机的地址!
address = InetAddress.getByName("localhost");
//打包
dp=new DatagramPacket(say, say.length,address,8800);
//发送
ds=new DatagramSocket();
ds.send(dp);

//接收
byte [] buf=new byte[1024];
dpTo=new DatagramPacket(buf, buf.length);
ds.receive(dpTo);
//我们看客服给我们回复了 什么 拆包
String reply=new String(dpTo.getData(),0,dpTo.getLength());
System.out.println(dpTo.getAddress().getHostAddress()+"说===》"+reply);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}


}

}

六、作业(U1项目)思路讲解(下周五考试、答辩)

1、信息都保留在xml格式文件中

2、账单用txt文件保存(I/O流)

3、套餐变更(标记)

4、退网(请勿删除用户,仅删除用户名下信息)

5、写完copy一份儿,优化代码并理清逻辑练习讲解

6、有余力考虑加点儿不一样的功能

七、老师辛苦了!

原文地址:https://www.cnblogs.com/wsnedved2017/p/6733736.html