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.youkuaiyun.com/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) {
}
}
}
}