TCP/IP协议 1.网络编程三要素 网络通讯的模型:请求(request)-响应(response),客户端(client)-服务端(server) 三要素:IP地址、端口号、协议(数据传输的规则) 2.特殊地址 127.0.0.1代表的本机地址 可用于测试本机的网络是否存在问题 DOS命令 ioconfig查看本机的IP地址 一个IP地址可以对应多个域名,但是一个域名在一个时刻只能对应一个IP。 3.端口号 1)每个网络程序都会至少有一个逻辑端口 2)用于标识进程的逻辑地址,不同进程的标识不同 3)有效端口:065535,其中01024是保留端口不能使用。 4)端口和协议有关,TCP和UDP的端口互不相干,同一个歇息的端口,不能重复但是不用歇息的可以重复。 4.tcp三次握手与四次挥手简述 https://blog.csdn.net/sssnmnmjmf/article/details/68486261 4.socket通信
案例分析:简单的Socket通信
服务端:
//服务端 public class Server { public static void main(String[] args) throws Exception { //1.创建ServerSocket 并且确定接收的端口 ServerSocket server = new ServerSocket(8080); //4.通过accept()接受客户端的信息 Socket socket = server.accept();
//5.接受客服端发送的消息 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); String reader = br.readLine(); System.out.println("接受客户端发送来的消息:" + reader); //6.对客户端发送消息 PrintStream ps = new PrintStream(socket.getOutputStream()); ps.println("我这是服务器发送过来的消息啊"); server.close(); socket.close(); ps.close();} }
客户端:
//客户端 public class Client { public static void main(String[] args) throws Exception { //2.创建Socket Socket socket = new Socket(“10.7.151.57”,8080);
//3.客户端向服务端发送消息 并打印在控制台 //通过seocket.getOutputStream()方法从客户端输出给服务器端的ServerSocket PrintStream print = new PrintStream(socket.getOutputStream()); print.println("你需要加点钱啊 小老弟"); //7.接受服务器发送来的消息 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); System.out.println(br.readLine()); socket.close(); print.close(); br.close();} }
案例2: 服务器端:/**
服务器和客户端的数据交互 *///服务端 public class Server { public static void main(String[] args) throws Exception { //1.创建ServerSocket ServerSocket server = new ServerSocket(8080); Socket socket = server.accept();
//3.接受客服端发送的消息 ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); User user = (User) ois.readObject(); //这里返回flag变量 而不是结果 是因为在真正开发的过程中 前后端的交互 你无法保证前段是网页还是app String flag = null; if("飞龙在天".equals(user.getUsername()) ){ flag = "-1"; }else{ flag = "1"; } //4.对客户端回复消息 PrintStream ps = new PrintStream(socket.getOutputStream()); ps.println(flag); server.close(); socket.close(); ps.close();} }
客户端: package com.dream.tcp03; /*
c/s 用户注册 */ import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.ObjectOutputStream; import java.io.PrintStream; import java.net.Socket; import java.util.Scanner;//客服端 public class Client { public static void main(String[] args) throws Exception { Socket socket = new Socket(“10.7.151.57”,8080);
//2.客户端向服务端发送消息 并打印在控制台 ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); System.out.println("注册开始!"); Scanner scan = new Scanner(System.in); System.out.println("输入你的用户名:"); String username = scan.next(); System.out.println("请输入你的密码:"); String password = scan.next(); System.out.println("请输入的你的性别:"); String sex = scan.next(); System.out.println("请输入你的爱好:"); String hobbit = scan.next(); oos.writeObject(new User("飞龙在天","123456","男","吃饭睡觉打豆豆")); scan.close(); //5.接受服务器发送来的消息 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); //读取从服务器发来的消息 String readline = br.readLine(); if("1".equals(readline) ){ System.out.println("注册成功"); }else{ System.out.println("注册失败"); } socket.close(); oos.close(); br.close();} }
用户类: package com.dream.tcp03;
public class User { String username; String password; String sex; String hobbit; public User(String username, String password, String sex, String hobbit) { super(); this.username = username; this.password = password; this.sex = sex; this.hobbit = hobbit; } public User() {
} public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getHobbit() { return hobbit; } public void setHobbit(String hobbit) { this.hobbit = hobbit; } @Override public String toString() { return "User [username=" + username + ", password=" + password + ", sex=" + sex + ", hobbit=" + hobbit + "]"; }}
案例三:文件的上传和下载 服务器端: package com.dream.tcp04;
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.net.ServerSocket; import java.net.Socket;
public class Server2 {
public static void main(String[] args) throws Exception { //创建ServerSocket 确定端口号 ServerSocket server = new ServerSocket(8080); //从客户端获得信息 Socket socket = server.accept(); //读取server.accpet()获得到的信息 BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); //将文件进行输出 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy2.avi")); byte[] b = new byte[1024]; int len; while((len = bis.read(b)) != -1 ){ bos.write(b,0,len); } server.close(); bos.close(); }}
客户端: package com.dream.tcp04;
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.net.Socket;
public class Client2 {
public static void main(String[] args) throws Exception { //创建Socket 并指向相应IP地址的服务器和端口号 Socket socket = new Socket("127.0.0.1",8080); //将文件输入到程序 变成字节 BufferedInputStream bis = new BufferedInputStream(new FileInputStream("飞龙在天.avi")); //将程序中的字节 上传到socket中 BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); byte[] b = new byte[1024]; int len; while((len = bis.read(b)) != -1 ){ bos.write(b,0,len); } //在上传到socket时 记得刷一下 bos.flush(); socket.close(); bis.close(); bos.close(); }}
5.InetAddresspackage com.dream.inetaddress;
import java.net.InetAddress;
/*
Inetaddress 类似于工具类的使用
其内部存在的方法全是内部类 */ public class Test01 { public static void main(String[] args) throws Exception { //获取域名对应的IP地址 InetAddress ia = InetAddress.getByName(“www.taobao.com”); System.out.println(ia);
//一个域名对应的是多个IP地址 //获得域名对应的所有的IP地址 InetAddress[] ia2 = InetAddress.getAllByName(“www.baidu.com”); for(InetAddress i : ia2){ System.out.println(i); }
//获取本机的IP地址 InetAddress localHost = InetAddress.getLocalHost(); System.out.println(localHost);} } 工具类 其中都是静态方法直接进行调用
多对多的聊天 服务端: package com.dream.tcp3;import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap;
/*
多人之间的聊天 一个服务端 多个客户端
逻辑顺序
第一步:在Server端创建ServerSocket
第二步:在Client客户端创建Socket 选择指向的服务端IP地址和端口号
第三步: 客户端发送消息给服务端
第四步:服务端接受各个客户端的消息
第五步: 创建Receive1类 开辟新线程 封装接受消息
第六步: 在Client客户端进行调用Receivel类 */ public class Server1 { //创建HashMap 进行存储不同客户端(IP地址)发来的消息 对应不同的socket 方便进行返回和调用 //放在成员变量并且进行public、static修饰 就是方便进行调用 public static HashMap<String,Socket> map = new HashMap<>(); public static void main(String[] args) throws Exception { //1.创建ServerSocket ServerSocket server = new ServerSocket();
//接受各个客户端的消息 while(true){ Socket socket = server.accept();
//获得当前客户端的IP地址 String key = socket.getInetAddress().getHostAddress(); //将IP地址存储到map集合中 map.put(key, socket); //创建新的线程ServerThread new ServerThread(socket).start();} } }
客户端: package com.dream.tcp3;
import java.io.PrintStream; import java.net.Socket; import java.util.Scanner;
public class Client1 { public static void main(String[] args) throws Exception { //2.创建Socket指向想要传输的IP地址和端口号 //这是自身机子上的所以 就127.0.0.1代表自身 Socket socket = new Socket(“127.0.0.1”,8080); Scanner scan = new Scanner(System.in);
//3.客户端发送消息给服务端 PrintStream ps = new PrintStream(socket.getOutputStream()); //六.在Client客户端进行调用Receivel类 //接收从服务端发来的消息 new Receive(socket).start();; while(true){ ps.println("小老弟:" + scan.next()); }} }
Receive类 package com.dream.tcp3;
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; //4.创建Receive1类 开辟新线程 封装接受消息 public class Receive1 extends Thread{ private BufferedReader br ;
public Receive1(Socket socket){ //由于是聊天 肯定最后为字符 所以用字符缓冲流+字节转字符流进行修饰 //需要用socket方法 所以用有参构造方法将socket传进来 //从socket接受到信息(有可能是客户端传给服务端 也有可能是服务端传送给客户端的) try { br = new BufferedReader(new InputStreamReader(socket.getInputStream())); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void run() { try { //读取从socket中获取的进行转换为字符流后的信息 String readLine = br.readLine(); System.out.println(readLine); } catch (IOException e) { } }}
ServerThread类 package com.dream.tcp3;
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.util.Set; import java.util.Map.Entry;
/**
多人之间的聊天 一个服务端 多个客户端@author Administrator*/ //创建一个新的线程 每有一个客户端就创建一个线程 public class ServerThread1 extends Thread {
private Socket socket; public ServerThread1(Socket socket){ this.socket = socket; } @Override public void run() { BufferedReader br = null; try { //接受来自客户端的消息 br = new BufferedReader(new InputStreamReader(socket.getInputStream())); } catch (IOException e) { } //循环接受来自客户端的消息 while(true){ try { String readLine = br.readLine(); System.out.println(readLine); //向其他的客户端发送消息 Set<Entry<String, Socket>> entrySet = Server.map.entrySet(); for(Entry<String,Socket> entry : entrySet){ String key = entry.getKey(); Socket value = entry.getValue(); //如果当前的key的值不等于当前的IP地址 进行向客户端发送消息 if(!key.equals(socket.getInetAddress().getHostName())){ PrintStream ps = new PrintStream(value.getOutputStream()); ps.println(readLine); } } } catch (IOException e) { } } }}