IP协议
计算机网络通信三要素:
- 明确的IP地址
- 一致的端口号
- 传输协议一致
面试题
1:Ip地址是用来标记网络中计算机的唯一识别方式
2:端口号是同来标记计算机中的所运行的每一个程序的
3:传输协议分为TCP和UDP
4:TCP和UDP的区别
TCP协议(传输控制协议) :属于面向有连接的、传输速度慢、安全性高、没有传输数据大小限定特点:必须是经过三次握手之后,在建立连接通道后,才可以传输数据
UDP协议(数据报文协议):属于面向无连接、传输速度快、安全性低、传输的数据必须限定在64K以内,不适应于传输数据较大、对数据安全的要求的程序
5:计算机网络中三次握手:
第一次客户端发送连接请求
第二次服务端发送收到确认
第三次互相通信
6:HTTPS和HTTP区别
https需要到ca(数字证书颁发机构)申请证书(这套数字证书其实就是一对公钥和私钥,私钥存放在服务端,公钥发给客户端用),一般都要钱
http是超文本传输协议,信息是明文传输。
7:各种服务的端口号
服务 | 端口号 | 服务 | 端口号 |
---|---|---|---|
FTP | 21 | SSH | 22 |
telnet | 23 | SMTP | 25 |
Domain | 53 | HTTP | 80 |
POP3 | 110 | NTP | 123 |
MySQL | 3306 | SQL Server | |
POP-2 | 109 |
TCP客户端和服务端通信
TCP连接会用到一个特殊的类:ServerSocket
此类实现了服务器套接字,服务器套接字等待请求网络传入
//构造方法,创建非绑定服务器套接字
ServerSocket()
//创建绑定到特定端口的服务器套接字
ServerSocket(int port)
//倾听并接收到此套接字的连接,服务器会一直阻塞,等待客户端连接
Socket accept()
初次连接通信
服务端 :
public static void main(String[] args) throws IOException {
System.out.println("服务器启动中...");
//创建服务端对象
ServerSocket ss = new ServerSocket(8888);
//获取客户端对象
Socket server = ss.accept();//执行到此时,会进入阻塞状态
//基于客户端对象获取服务端的输入流
InputStream is =server.getInputStream();
byte[] b = new byte[1024];
int len = is.read(b);
//打印接收到数据
System.out.println(new String(b,0,len));
//向客户端输入数据
OutputStream os = server.getOutputStream();
os.write("你好,client".getBytes());
os.close();
is.close();
server.close();
客户端:
public static void main(String[] args) throws IOException {
//创建socket对象,请求连接
Socket client = new Socket("localhost",8888);
//通过Socket对象获取OutputStream,向服务器写数据
OutputStream os = client.getOutputStream();
//向服务器中写数据
os.write("hello".getBytes());
//通过Socket对象获取OutputStream,解析回写的数据
InputStream is = client.getInputStream();
byte[] b = new byte[1024];
int len = is.read(b);
System.out.println(new String(b,0,len));
//刷新并关闭资源
os.flush();
is.close();
os.close();
client.close();
}
通信的时候需要先启动服务器,再启动客户端
实现服务端并发
将服务端一直开启,接收多次发来的数据
/**
* TCP并发
* @author zhuang
*
* 2020年11月18日 下午8:20:01
*/
public class ServerRunnable implements Runnable{
//客户端对象
Socket server = null;
public ServerRunnable() {
}
public ServerRunnable(Socket server) {
this.server = server;
}
@Override
public void run() {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(server.getInputStream());
bos = new BufferedOutputStream(new FileOutputStream(System.currentTimeMillis()+".png"));
byte[] b = new byte[1024*8];
int len = 0;
while((len = bis.read(b)) != -1) {
bos.write(b, 0, len);
bos.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(bos != null)
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(bis != null)
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* TCP文件传输客户端
* @author zhuang
*
* 2020年11月18日 下午8:20:56
*/
public class TransFileClient {
public static void main(String[] args) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("abc2.jpg"));
Socket socket = new Socket("localhost",8888);
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
byte[] b = new byte[1024*8];
int len = 0;
while((len = bis.read(b)) != -1) {
bos.write(b, 0, len);
bos.flush();
}
System.out.println("文件上传完毕");
bos.close();
socket.close();
bis.close();
}
}
/**
* TCP传输服务端
* @author zhuang
*
* 2020年11月18日 下午8:21:56
*/
public class TransFileServer {
public static void main(String[] args) throws IOException {
System.out.println("服务器启动中。。。");
ServerSocket ss = new ServerSocket(8888);
while(true) {
Socket server = ss.accept();
ServerRunnable sr = new ServerRunnable(server);
new Thread(sr).start();
System.out.println("文件上传成功");
}
}
}
UDP传输
DatagramSocket:是一个底层使用UDP协议传输的对象
服务器端:
public static void main(String[] args) throws IOException {
//创建接收数据包的UDP对象
DatagramSocket server = new DatagramSocket(9999);
System.out.println("服务器已经准备好,等待客户端发送数据...");
byte[] buf = new byte[1024];//定义接收数据包
//接收数据包
DatagramPacket dp = new DatagramPacket(buf,buf.length);
server.receive(dp);
System.out.println("客户端 "+dp.getAddress().getHostAddress()+"已连接");
//利用数据包对象中的getLength()获取到实际接收到的数据长度
int len = dp.getLength();
//第一种方案,直接用byte数据,转换成字符串
String str = new String(buf,0,len);
System.out.println(str);
//第二种方案,使用Datagrampacket对象中的getData()方法
byte[] buf2 = dp.getData();
System.out.println(new String(buf,0,dp.getLength()));
server.close();
}
客户端:
public static void main(String[] args) throws IOException {
//创建UDP协议
DatagramSocket client = new DatagramSocket(8888);
//要发送的数据
byte[] buf ="发送UDP文件信息".getBytes();
InetAddress ip = InetAddress.getByName("localhost");
//创建数据包对象,9999属于服务端的端口号
DatagramPacket dp = new DatagramPacket(buf,buf.length,ip,9999);
//把数据包发送到指定的服务器程序
client.send(dp);
//关闭客户端
client.close();
}
多线程并发
客户端
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
System.out.println("发送端发送数据中。。。");
DatagramSocket ds = new DatagramSocket();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line = br.readLine()) != null) {
if("exit".equals(line)) {
break;}
else {
byte[] buf = line.getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length,InetAddress.getByName("localhost"),9999);
ds.send(dp);
}
}
ds.close();
System.out.println("发送结束");
}
多线程代码:
public class UdpServerRunnable implements Runnable{
DatagramSocket ds ;
public UdpServerRunnable() {
}
public UdpServerRunnable(DatagramSocket server) {
this.ds = ds;
}
@Override
public void run() {
DatagramSocket ds;
try {
ds = new DatagramSocket(9999);
while(true) {
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
try {
ds.receive(dp);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] b = dp.getData();
System.out.println(new String(b));
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
服务端:
public static void main(String[] args) throws IOException {
System.out.println("接收端启动中。。。");
DatagramSocket ds = new DatagramSocket(9999);
while(true) {
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf, buf.length);
ds.receive(dp);
byte[] b = dp.getData();
System.out.println(new String(b));
}
}