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、有余力考虑加点儿不一样的功能
七、老师辛苦了!