网络模型
OSI:
应用层 主要指的是是程序
表示层 将数据加密或者解密成二进制的数据
会话层 保持主机之间的连接
传输层 通过网络协议传输数据(TCP协议、UDP协议)
网络层 分配IP地址(IP地址)
网络数据链路层 保证准确性(MAC地址物理地址)
物理层 进行数据传输
TCP/IP模型
应用层
传输层
网络层
物理层
网络编程三要素:协议、地址、端口号
TCP:传输控制协议
特点:面向连接、安全可靠、效率低、基于字节流进行通信、数据大小无限制。
建立连接三次握手、断开连接四次挥手
通俗解释:打电话
UDP:数据报协议
特点:面向无连接、不安全、效率高、基于数据报包的形式通信、数据包大概在64kb
通俗解释:对讲机
基于TCP协议通信
通过客户端向服务端发送信息
//客户端
public class Client {
public static void main(String[] args) throws IOException {
//1、创建客户端Socket对象
Socket socket = new Socket("127.0.0.1",6666);
//2、通过Socket对象获取输出流对象
OutputStream out = socket.getOutputStream();
//3、通过输出流对象写出数据
//将字符串转换成字节数组 字符串.getBytes("字符集");
out.write("hello,我是客户端!!!".getBytes());
//4、关闭资源
out.close();
socket.close();
}
}
//服务器端
public class Server {
public static void main(String[] args) throws IOException {
//1、创建服务端端Socket对象
ServerSocket ss = new ServerSocket(6666);
//2、通过ServerSocket对象获取Socket对象
//ss.accept()阻塞式方法。直到有客户端与之建立连接才会继续向下执行
Socket socket = ss.accept();
//3、通过Socket对象获取输入流对象
InputStream in = socket.getInputStream();
//4、通过输入流对象读出数据
int len; //表示读取到的字节的长度
byte[] buf = new byte[1024]; // 表示缓冲区
while((len = in.read(buf)) != -1){
//将字节数组转转成字符串
String str = new String(buf,0,len);
System.out.println(str);
}
//5、关闭资源
in.close();
socket.close();
ss.close();
}
}
基于多线程实现客户端服务端通信
/**
* 客户端程序
*/
public class Client {
public static void main(String[] args) throws IOException {
//创建Scanner对象
Scanner sc = new Scanner(System.in);
while(true){
//1、创建客户端Socket对象
Socket socket = new Socket("localhost",6677);
//2、获取输出流对象
OutputStream out = socket.getOutputStream();
//3、通过输出流对象写出数据
//获取输入的内容 next():用于获取输入的字符串(以空格为标记进行获取) nextLine():用于获取输入的字符串(以回车为标记进行获取)
String words = sc.next();
if("886".equals(words)||"over".equals(words)){
//4、释放资源
out.close();
socket.close();
break;
}
out.write(words.getBytes());
//4、释放资源
out.close();
socket.close();
}
}
}
/**
* 服务端程序
*/
public class Server {
public static void main(String[] args) throws IOException {
//1、创建服务端Socket对象
ServerSocket ss = new ServerSocket(6677);
System.out.println("服务端已开启等待客户端连接....");
while(true){
//2、获取Socket对象
Socket socket = ss.accept();
//获取客户端发送的信息
String ip = socket.getInetAddress().getHostAddress();
//创建线程来处理客户端的请求
new Thread(new Runnable() {
@Override
public void run() {
try {
//3、通过Socket对象获取输入流
InputStream in = socket.getInputStream();
//4、通过输入流读取内容
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String readLine = br.readLine();
System.out.println(ip+":"+readLine);
//5、释放资源
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
实现客户端文件上传功能,并从服务端向客户端发送数据
/**
* 客户端程序
*/
public class Client {
//客户端向服务端发送图片
public static void main(String[] args) throws IOException {
//1、创建Socket对象
Socket socket = new Socket("192.168.73.210",8899);
//2、通过Socket获取输出流对象
OutputStream out = socket.getOutputStream();
//思路:从本地将图片读取出来,然后通过socket输出流立马写出去
FileInputStream fis = new FileInputStream("d:\\41.jpg");
byte[] buf = new byte[1024];
int len;
while((len = fis.read(buf))!=-1){
//3、通过输出流写出数据
out.write(buf,0,len);
}
//告知服务器这边已经写完了
socket.shutdownOutput();
//从服务端接收到返回信息
InputStream in = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
System.out.println(br.readLine());
//4、释放资源
in.close();
fis.close();
out.close();
socket.close();
}
}
/**
* 服务端程序
*/
public class Server {
public static void main(String[] args) throws IOException {
//1、创建ServerSocket对象
ServerSocket ss = new ServerSocket(8899);
System.out.println("图片服务器已开启....");
while(true){
//2、获取Socket对象
Socket socket = ss.accept();
//开启线程执行上传图片操作
new Thread(new UploadThread(socket)).start();
}
}
}
class UploadThread implements Runnable{
Socket socket;
public UploadThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
//通过socket对象获取输入流
try {
InputStream in = socket.getInputStream();
//思路:文件上传,读取到图片之后将图片保存在服务器上的upload文件夹中
String newFilename = UUID.randomUUID().toString().replace("-","");
FileOutputStream fos = new FileOutputStream("upload\\"+newFilename+".jpg");
byte[] buf = new byte[1024];
int len ;
while((len = in.read(buf))!=-1){
fos.write(buf,0,len);
}
//获取输出流向客户端发送数据
OutputStream out = socket.getOutputStream();
out.write(("success!!!"+"upload\\"+newFilename+".jpg").getBytes());
//4、关闭资源
out.close();
fos.close();
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
基于UDP协议通信
发送端发送数据到接收端
//发送
public class Send {
public static void main(String[] args) throws Exception {
//1、基于UDP协议创建Socket对象 无需指定端口号ip地址
DatagramSocket ds = new DatagramSocket();
//2、创建数据包对象
byte[] buf = "你好接收端".getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length, InetAddress.getByName("192.168.73.210"),9999);
//3、发送数据包
ds.send(dp);
//4、释放资源
ds.close();
}
}
//接收
public class Receive {
public static void main(String[] args) throws Exception {
//1、基于UDP协议创建Socket对象
DatagramSocket ds = new DatagramSocket(9999);
//2、创建数据包对象
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
//3、接受数据包 receive阻塞式的方法
ds.receive(dp);
//4、解析数据包的数据
//从数据包中获取数据
byte[] data = dp.getData();
//从数据包中获取InetAddress对象
InetAddress inetAddress = dp.getAddress();
//从数据包中获取端口号
int port = dp.getPort();
//获取数据包的数据字节数长度
int length = dp.getLength();
String str = new String(data,0,length);
System.out.println("ip:"+inetAddress.getHostAddress());
System.out.println("port:"+port);
System.out.println("data:"+str);
//5、释放资源
ds.close();
}
}