网络编程UDP/TCP IP

1 篇文章 0 订阅
1 篇文章 0 订阅

网络编程

10.网络编程的概念

10.1)网络编程的三要素

网络编程的三要素

举例:
	1)找到高圆圆---->ip地址 
	2)对它说话 ----(耳朵说)----端口号
	3)找到她了,对她说:	---->协议
			i love you(比如:不懂英语,说中文) 
			
协议   ip地址    端口号
网络协议
	UDP和TCP
	
	UDP和TCP协议的区别:
1)是否需要建立连接通道
		UDP:不需要建立通道  (QQ聊天,发短信)
		TCP:需要建立连接通道(打电话...)
		
2)是否是可靠连接(是否安全)
		UDP:是一种不可靠连接,不安全--执行效率高
		TCP:是一种可靠连接,服务器端一直阻塞状态(同步的---安全性),执行效率低
				三次握手,四次挥手!
3)共同点
		UDP/TCP ---两端都需要有Socket(Socket编程)
应用协议
	http协议
	https协议(比上http协议)
第一要素:
	ip地址
	192.168.138.1:	使用点分十进制法
	
	A类IP地址:第一段号码为网络号码,剩下的三段号码为本地计算机的号码  (政府部门)
	B类IP地址:前二段号码为网络号码,剩下的二段号码为本地计算机的号码 (大学校园)
	C类IP地址:前三段号码为网络号码,剩下的一段号码为本地计算机的号码(私人地址)
	127.0.0.1:回环地址:表示本机	---- 域名:localhost
	xxx.xxx.xxx.255 广播地址
第二个要素:端口号
使用360软件---查看当前计算机中每个软件 的端口号
有效端口号:0-65535
		 0-1024:保留端口号
http://www.baidu.com
http://192.168.25.1:80(可以不写)/xx
	一般:80端口号:是不写的(省略)
常见端口号
	tomcat: 8080
	redis:6575.. (数据库---非关系型数据库  key-value )
	mysql软件:3306

10.2)获取ip地址

package com.qianfeng_net_07;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * java.net.InetAddress类:互联网ip地址统称
 * 这个类没有构造方法,不能直接创建对象!,提供一些成员方法使用:静态的
 * 
 * 
 * Runtime类: 单例模式
 * 提供静态方法,返回该类本身
 * 
 * public static InetAddress getByName(String host):
 * 参数为:主机名称:
 * 
 * 
 * 成员方法
 * public String getHostAddress()返回 IP 地址字符串(以文本表现形式)。 
 * public String getHostName():获取主机名
 * 
 * @author zhangyang
 *
 */
public class InetAddressDemo {
	
	public static void main(String[] args) throws UnknownHostException {
		//获取ip地址:字符串形式
		//public static InetAddress getByName(String host)
//		InetAddress inetAddress = InetAddress.getByName("LAPTOP-BHL76J0S") ;
		InetAddress inetAddress = InetAddress.getByName("10.12.156.36") ;
		
		// * public String getHostAddress()
		String ip = inetAddress.getHostAddress() ;
		System.out.println(ip);//10.12.156.36
		
		//public String getHostName()
		String name = inetAddress.getHostName() ;
		System.out.println(name);//APTOP-BHL76J0S
		
		
	}
}

10.3)UDP协议发送端的步骤

package com.qianfeng_net_08;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * UDP协议发送端的步骤
 * 
 * 1)创建发送端的Socket对象
 * 2)数据数据报包对象:DatagramPacket
 * 3)发送数据
 * 4)关闭资源
 * 
 * @author zhangyang
 *
 */
public class SendDemo {
	
	public static void main(String[] args) throws IOException {
		
		//1)创建发送端的Socket对象
		//DatagramSocket
		//此类表示用来发送和接收数据报包的套接字。
		//public DatagramSocket()
		DatagramSocket ds = new DatagramSocket() ;
		
		//2)创建数据数据报包对象:DatagramPacket
		//数据报包用来实现无连接包投递服务
		//public DatagramPacket(byte[] buf,
      //  int length,
        //InetAddress address,
        //int port)
		//参数1:当前发送数据的字节数组
		//参数2:当前数据的实际长度
		//参数3:ip地址对象
		//参数4:端口号:0-1024保留端口 (0-65535)
		
		String s = "hello,udp,我来了" ;
		byte[] bytes = s.getBytes() ;
		int length = bytes.length ;
		DatagramPacket dp = new DatagramPacket(bytes, length,
				InetAddress.getByName("10.12.156.36"), 10086) ;
		
		//3)发送数据报包 
		//public void send(DatagramPacket p)

		ds.send(dp);
		
		//释放资源
		ds.close();
	}
}

10.4)UDP协议接收端的实现步骤

package com.qianfeng_net_08;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * UDP协议接收端的实现步骤
 * 
 * 1)创建接收端的Socket对象,绑定端口号
 * 2)创建一个数据报包---DatagramPacket:当前接收容器
 * public DatagramPacket(byte[] buf,int length)
 * 3)接收数据
 * 4)从接收容器中解析实际数据
 * 5)展示数据
 * @author zhangyang
 *
 */
public class ReceiveDemo {
    
    public static void main(String[] args)  throws IOException{
        //1)创建接收端的Socket对象,绑定端口号
//      public DatagramSocket(int port)
        DatagramSocket ds = new DatagramSocket(10086) ;
        
        //2)创建一个数据报包---DatagramPacket:当前接收容器
         // public DatagramPacket(byte[] buf,int length)
        //接收容器大小,一般是1024或者1024的倍数
        byte[] bytes = new byte[1024] ;
        int length = bytes.length ;
        DatagramPacket dp = new DatagramPacket(bytes, length) ;
        
        //3)接收数据
//      public void receive(DatagramPacket p)
        ds.receive(dp);
        
        //4)解析当前接收容器中的实际数据
        //public byte[] getData():获取缓冲区数据中实际字节数组
        //public int getLength():获取缓冲区中实际长度
        byte[] buf = dp.getData() ;
        int length2 = dp.getLength() ; 
        
        //获取接收端发送的数据:ip地址
//      public InetAddress getAddress()
        InetAddress address = dp.getAddress() ;
        String ip = address.getHostAddress() ;
        
        //展示数据
        String s = new String(buf,0,length2) ;
        System.out.println("data is: "+s+",from  "+ip);
        
        //关闭资源
        ds.close();
        
    }
}

1.UDP发送端键盘录入数据,接收端不断接收数据(不关闭)

1.1)发送端键盘录入数据

package com.qianfeng.udp_01;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * 
 * 需求
 * UDP
 *  发送端键盘录入数据,接收端不断接收数据(不关闭)
 * 
 * 
 * 键盘录入数据
 *  Scanner
 *  使用字符流的方式
 *  BufferedReader(new InputStreamReader(System.in))
 * @author zhangyang
 *
 */
public class SendDemo {
    
    public static void main(String[] args) throws IOException {
        
        //1)创建发送端的Socket对象
        DatagramSocket ds = new DatagramSocket() ;
        
        //2)键盘录入数据
        //创建bufferedReader类对象
        BufferedReader br = new BufferedReader(
                new InputStreamReader(System.in)) ;
        //一次读取一行内容
        String line = null ;
        while((line=br.readLine())!=null) {
            //自定义结束条件
            if(line.equals("886")) {
                break ;
            }
            
            
            //line:发送的数据
            byte[] bytes = line.getBytes() ;
            int length = bytes.length ;
            //创建数据报包对象
            DatagramPacket dp = new DatagramPacket(
                    bytes, 
                    length, 
                    InetAddress.getByName("10.12.156.36"),
                    10000) ;
            
            //发送数据
            ds.send(dp);
            
        }
        
        //释放资源
        ds.close();
        
        
    }
}

1.2)接收端不断接收数据(不关闭)

package com.qianfeng.udp_01;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

//接收端不断接收收据,并解析
public class ReceiveDemo {

    public static void main(String[] args) throws IOException {
        
        //创建一个接收端的Socket
        DatagramSocket ds = new DatagramSocket(10000) ;
        
        //不断接收数据
        while(true) {
            //创建接收容器
            byte[] bytes = new byte[1024] ;
            int length = bytes.length ;
            DatagramPacket dp = new DatagramPacket(bytes , length) ;
            
            //接收
            ds.receive(dp);
            
            //解析真实数据
            String str = new String(dp.getData(), 0, dp.getLength()) ;
            //获取ip地址
            String ip = dp.getAddress().getHostAddress() ;
            
            //展示数据
            System.out.println("data is :"+str+"from "+ip);
        }
        //接收端不关闭
    }
}

2.多线程:需要在一个窗口下进行聊天,发送和接收数据

2.1)多线程的实现

package com.qianfeng.udp_02;

import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * 
 * 需要在一个窗口下进行聊天,发送和接收数据
 * 
 * 发送端会开启发送端的线程!
 * 接收端开启接收端的线程!
 * 
 * 多线程的实现方式:
 *  1)Thread类:继承自它
 *  2)实现Runnable接口(静态代理)
 *  3)线程池
 * 分析:
 * 
 *  1)发送端和接收端都需要有Socket 都需要在当前用户线程(main)中创建出来
 *  2)多线程实现方式2
 *   SendThread /ReceiveThread 实现Runnable接口重写run方法   (这两个作为资源类)
 *   这两个资源类对象需要将上面Socket对象传递进来
 * 
 *  3)创建Thread类对象,将上面的SendThread和ReceiveThread作为参数传递
 *  4)启动线程
 * 
 * 
 * @author zhangyang
 *
 */
public class ChatRoom {
    
    public static void main(String[] args) {
        try {
            //发送端的Scoket
            DatagramSocket sendDs = new DatagramSocket() ;
            //接收端Socket
            DatagramSocket receDs = new DatagramSocket(12306) ;
            
            //创建资源类对象:多线程的方式2
            SendThread st = new SendThread(sendDs) ; 
            ReceiveThread rt = new ReceiveThread(receDs) ;
            
            //创建Thread类对象
            Thread t1 = new Thread(st) ;
            Thread t2 = new Thread(rt) ;
            t1.start();
            t2.start();
            
        } catch (SocketException e) {
            e.printStackTrace();
        }
        
    }
}

2.2)发送端的资源类

package com.qianfeng.udp_02;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

//发送端的资源类
public class SendThread implements Runnable {
    private DatagramSocket ds ; 
    
    public SendThread(DatagramSocket ds) {
        this.ds  = ds;
    }

    @Override
    public void run() {
        try {
                // 键盘录入数据
                // 创建bufferedReader类对象
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                // 一次读取一行内容
                String line = null;
                while ((line = br.readLine()) != null) {
                    // 自定义结束条件
                    if (line.equals("886")) {
                        break;
                    }
    
                    // line:发送的数据
                    byte[] bytes = line.getBytes();
                    int length = bytes.length;
                    // 创建数据报包对象
                    DatagramPacket dp = new DatagramPacket(bytes, length, 
                            InetAddress.getByName("10.12.156.36"), 12306);
    
                    // 发送数据
                    ds.send(dp);

            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(ds!=null) {
                ds.close();
            }
        }

    }

}

2.3)接收端的资源类

package com.qianfeng.udp_02;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

//接收端的资源类
public class ReceiveThread implements Runnable {
    
    private DatagramSocket ds ;
    
    public ReceiveThread(DatagramSocket ds) {
        this.ds = ds ;
    }

    @Override
    public void run() {

        
        try {
            // 不断接收数据
            while (true) {
                // 创建接收容器
                byte[] bytes = new byte[1024];
                int length = bytes.length;
                DatagramPacket dp = new DatagramPacket(bytes, length);

                // 接收
                ds.receive(dp);

                // 解析真实数据
                String str = new String(dp.getData(), 0, dp.getLength());
                // 获取ip地址
                String ip = dp.getAddress().getHostAddress();

                // 展示数据
                System.out.println("data is :" + str + "from " + ip);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

3.TCP/IP协议:发送接收数据

3.1)客户端的实现步骤(发送)

package com.qianfeng.tcp_03;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * 
 * TCP协议
 * 
 * 基本使用:
 * 客户端的实现步骤
 *  1)创建客户端的Socket对象        java.net.Socket(套接字)
 * public Socket(String host,int port)
 *  2)获取客户端通道内输出流,写入内容
 *  3)关闭资源
 * 
 * @author zhangyang
 *
 */
public class ClientDemo {
    
    public static void main(String[] args) throws  IOException {
        
        //创建客户端的Socket对象
        //public Socket(String host,int port)
        Socket s = new Socket("10.12.156.36", 8888) ;
        
        //获取客户端通道内输出流,写入内容
        //public OutputStream getOutputStream()

        OutputStream out = s.getOutputStream() ;
        out.write("hello,TCP,我来了".getBytes());
        
        //释放资源
        s.close();
    }
}

3.2)服务器端基本使用(接收)

package com.qianfeng.tcp_03;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 
 * TCP
 * 服务器端基本使用
 * 
 * 步骤
 *  1)创建服务器端的Socket对象,绑定端口
 *  2)进入阻塞状态,监听客户端连接!
 *  3)获取动态内输入流,读数据
 *  4)展示数据
 *  5)释放资源
 * @author zhangyang
 *
 */
public class ServerDemo {
    
    public static void main(String[] args) throws IOException {
        //1)创建服务器端的Socket对象,绑定端口
        //public ServerSocket(int port)
        ServerSocket ss = new ServerSocket(8888) ;
        
        //2)进入阻塞状态,监听客户端连接!
        //public Socket accept()
        Socket s = ss.accept() ;
        
        //3)获取动态内输入流,读数据
        //public InputStream getInputStream()
        InputStream in = s.getInputStream() ;
        //读数据
        //一次读取一个字节数组
        byte[] bytes = new byte[1024] ;
        int len = in.read(bytes) ;
        //展示数据
        String clienStr = new String(bytes,0,len) ;
        //public InetAddress getInetAddress()
        String ip = s.getInetAddress().getHostAddress() ;
        //输出
        System.out.println("data is:"+clienStr+",from :"+ip);
        //释放资源
        ss.close();
    }
}

4.客户端发送数据,服务端接收并反馈

4.1)客户端发送数据并接收反馈信息

package com.qianfeng.tcp_04;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
 * 
 * 
 * 客户端发送数据"hello,Server,我来了"
 * 服务器端将数据读取出来,展示
 * 
 * 服务器端还需要加入反馈操作,"我收到了"
 * 客户端需要将反馈信息读取 出来
 * 
 * @author zhangyang
 *
 */
public class ClientDemo {
	
	public static void main(String[] args) throws IOException {
		
		//创建客户端的socket
		Socket socket = new Socket("10.12.156.36",6666) ;
 	
		//获取通道内的输出流
		OutputStream out = socket.getOutputStream() ;
		out.write("hello,Server,我来了".getBytes());
		
		
		//读取服务器端的反馈数据
		//获取通道内的输入流对象
		InputStream in = socket.getInputStream() ;
		//一次读取一个字节数组
		byte[] bytes = new byte[1024] ;
		int len = in.read(bytes) ;
		//展示数据
		String serverStr = new String(bytes, 0, len) ;
		System.out.println(serverStr);
		
		
		//释放资源
		socket.close();
	}
}

4.2)服务器端还需要加入反馈操作,“我收到了”

package com.qianfeng.tcp_04;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务器端还需要加入反馈操作,"我收到了"
 * 客户端需要将反馈信息读取 出来
 * 
 * 注意事项:
 * 服务器端不要开启多次,就会出现BindException:绑定异常: 端口号被占用!
 * 
 * @author zhangyang
 *
 */
public class ServerDemo {
	
	public static void main(String[] args) throws IOException {
		
		//创建ServerSocket对象
		ServerSocket ss = new ServerSocket(6666) ;
		
		//监听客户端的链接
		Socket socket = ss.accept() ;
		
		//获取通道输入流,读取数据
		InputStream in = socket.getInputStream() ;
		//一次读取一个字节数组
		byte[] bytes = new byte[1024] ;
		int len = in.read(bytes) ;
		//展示数据:客户端发来的数据
		String clientStr = new String(bytes, 0, len) ;
		System.out.println(clientStr);
		
		
		//服务器端反馈给客户端
		//获取通道内的输出流对象
		OutputStream out = socket.getOutputStream() ;
		out.write("数据已经收到了".getBytes());
		
		
		
		//释放资源
		ss.close();
	}
}


5键盘录入:BufferedReader:客户端发送,服务端不断将数据展示在控制台

5.1键盘录入客户端数据

package com.qianfeng.tcp_05;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

/**
 * 需求
 * 	键盘录入:BufferedReader
 * 1)客户端不断键盘录入数据,服务器端不断将数据展示在控制台上
 * 
 * 
 *
 * @author zhangyang
 */
public class ClientTest {

	public static void main(String[] args) throws IOException {
		
		//创建客户端Socket
		Socket socket = new Socket("10.12.156.36", 2222) ;
		//)客户端不断键盘录入数据
		//创建字符输入流:BufferedReader
		BufferedReader br =
				new BufferedReader(new InputStreamReader(System.in)) ;
		
		//OutputStream getOutputStream():通道内的字节输出流
		//输出流需要和BufferedReader对应:  BufferedWriter:字符输出流
		//将节输出流封装成BuffferedWriter   :字符流通向字节流的桥梁 OutputStreamWriter
		BufferedWriter bw = new BufferedWriter(
				new OutputStreamWriter(socket.getOutputStream())) ;
		
		//一次读取一行数据:键盘录入 数据,写入到BufferedWriter中
		String line = null ;
		while((line=br.readLine())!=null) {
			
			//结束条件
			if(line.equals("over")) {
				break ;
			}
			
			//录入一行,写入到bw流中
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		
		//释放资源
		socket.close();
		
		
		
		
		
	}
}


5.1键盘录入客户端数据

package com.qianfeng.tcp_05;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

/**
 * 需求
 * 	键盘录入:BufferedReader
 * 1)客户端不断键盘录入数据,服务器端不断将数据展示在控制台上
 * 
 * 
 *
 * @author zhangyang
 */
public class ClientTest {

	public static void main(String[] args) throws IOException {
		
		//创建客户端Socket
		Socket socket = new Socket("10.12.156.36", 2222) ;
		//)客户端不断键盘录入数据
		//创建字符输入流:BufferedReader
		BufferedReader br =
				new BufferedReader(new InputStreamReader(System.in)) ;
		
		//OutputStream getOutputStream():通道内的字节输出流
		//输出流需要和BufferedReader对应:  BufferedWriter:字符输出流
		//将节输出流封装成BuffferedWriter   :字符流通向字节流的桥梁 OutputStreamWriter
		BufferedWriter bw = new BufferedWriter(
				new OutputStreamWriter(socket.getOutputStream())) ;
		
		//一次读取一行数据:键盘录入 数据,写入到BufferedWriter中
		String line = null ;
		while((line=br.readLine())!=null) {
			
			//结束条件
			if(line.equals("over")) {
				break ;
			}
			
			//录入一行,写入到bw流中
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		
		//释放资源
		socket.close();
		
		
		
		
		
	}
}


5.2)服务器端不断将数据展示在控制台上

package com.qianfeng.tcp_05;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

//服务器端不断将数据展示在控制台上
public class ServerTest {

	public static void main(String[] args) throws IOException {
		
		//创建服务器端的Socket对象
		ServerSocket ss = new ServerSocket(2222) ;
		
		//监听客户端连接
		Socket socket = ss.accept() ;
		
		//不断的去读取数据
		//获取通道内输入流:将封装 成BufferedReader
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())) ;
		String line = null ;
		while((line=br.readLine())!=null) {
			//输出数据
			System.out.println(line);
		}
			
		//服务器端不关闭
	}
}


6.客户端不断键盘录入数据,服务器端将数据输出在某个文件中

6.1)客户端不断键盘录入数据

package com.qianfeng.tcp_06;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

/**
 *  2)客户端不断键盘录入数据,服务器端将数据输出在某个文件中
 */
public class ClientTest {


	public static void main(String[] args) throws IOException {

		// 创建客户端Socket
		Socket socket = new Socket("10.12.156.36", 2222);
		// )客户端不断键盘录入数据
		// 创建字符输入流:BufferedReader
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		// OutputStream getOutputStream():通道内的字节输出流
		// 输出流需要和BufferedReader对应: BufferedWriter:字符输出流
		// 将节输出流封装成BuffferedWriter :字符流通向字节流的桥梁 OutputStreamWriter
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

		// 一次读取一行数据:键盘录入 数据,写入到BufferedWriter中
		String line = null;
		while ((line = br.readLine()) != null) {

			// 结束条件
			if (line.equals("over")) {
				break;
			}

			// 录入一行,写入到bw流中
			bw.write(line);
			bw.newLine();
			bw.flush();
		}

		// 释放资源
		socket.close();

	}
}


6.2)服务器端将数据输出在某个文件中

package com.qianfeng.tcp_06;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

//服务器端将数据输出在某个文件中
public class ServerTest {

	public static void main(String[] args) throws IOException {
		
		//创建服务器端的Socket
		ServerSocket ss = new ServerSocket(2222) ;
		
		//监听客户端连接
		Socket socket = ss.accept() ;
		
		//封装通道内的字节输入流:BufferedReader 先读取客户端写过来的数据
		BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())) ;
		
		//创建BufferedWriter流对象,将服务器端读取的数据写入到文件中
		BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt")) ;
		
		//一次读取一行
		String line = null ;
		while((line=br.readLine())!=null) {
			//将内容写入到文件中
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		//关闭资源
		bw.close();
		socket.close();
	}
}

7客户端–服务端<–>文件复制读写(反馈信息)

7.1)客户端将文件(ReceiveDemo.java)写入通道流中

package com.qianfeng.tcp_08;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/*
3)客户端将当前项目下ReceiveDemo.java文件 写入到通道内的流中
  服务器端将客户端的文本进行复制:到当前项目Copy.java文件中  
  //加入服务器端的反馈?
  问题:
  	服务器端和客户端程序没有结束,但是文件已经复制完毕!  	
 String readLine() :返回为null,仅仅表示文件已经读完了,
 但是服务器端不知道客户端的文件是否已经写入到通道流中(是否应写入完毕),就等待着客户端告诉服务器端"已经写入完毕"
 当前客户端没有告诉服务器端,是否写入完毕,那么客户端也一直等待着服务器的反馈,就出现互相等待了! 
 解决方案
 	1)在客户端自定义一个结束标记
 			通道输出流(BufferedWriter)写入"over",服务器端读取到"over",直接结束!			
 	2)在客户端Socket中:结束的方法 "告诉服务器,这里面没有内容写入"
 		public void shutdownOutput()
	
*/

public class UploadClient {
	
	public static void main(String[] args) throws IOException {
		
		//创建Scoket对象
		Socket s = new Socket("10.12.156.36", 5555) ;
		
		//创建字符输入流BufferedReader
		BufferedReader br = new BufferedReader
				(new FileReader("ReceiveDemo.java")) ;
		
		//封装通道内的字节输出流
		BufferedWriter bw =
					new BufferedWriter(
							new OutputStreamWriter(s.getOutputStream())) ;
		
		//将文件的内容写到bw流对象中
		String line = null ;
		while((line=br.readLine())!=null) { //readLine():阻塞式方法
			//写入
			bw.write(line);
			bw.newLine();			
			bw.flush();
		}		
		/**
		 * 方案1
		 * //自定义一个结束标记
		bw.write("over");
		bw.newLine();
		bw.flush();
		 */		
		//方案2
//		public void shutdownOutput()://禁用此套接字的输出流:告诉服务器端,没有内容写入到通道流中
		s.shutdownOutput();	
		//获取通道内的字节输入流,读取服务器端的反馈
		//将字节输入流---封装BufferedReader
		BufferedReader br2 = new BufferedReader
				(new InputStreamReader(s.getInputStream())) ;
		//readLine()
		String serverMsg = br2.readLine() ;
		System.out.println(serverMsg);		
		//关闭
		br.close();
		s.close();
	}
}

7.2)服务端将通道流中的文件写入指定文件中(Copy.java),加上反馈信息

package com.qianfeng.tcp_08;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class UploadServer {
	
	public static void main(String[] args)  throws IOException{
		
		//创建ServerSocket对象
		ServerSocket ss = new ServerSocket(5555) ;
		
		//监听链接
		Socket socket = ss.accept() ;
		
		//封装通道内的字节输入流
		BufferedReader br = new BufferedReader
				(new InputStreamReader(socket.getInputStream())) ;
		
		//创建BufferedWriter将流中数据进行复制
		BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java")) ;
		
		String line = null ;
		while((line=br.readLine())!=null) {//阻塞式方法
			/*
			//读取客户端的自定义标记
			if("over".equals(line)) {
				break ;
			}
			*/
			
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		
		
		//客户端的文本文件,服务器端输出到另一个文件中,如果复制完毕
		//加入服务器端的反馈?
		//获取通道内的字节输出流---封装成BufferedWriter
		BufferedWriter bw2 = new BufferedWriter(
				new OutputStreamWriter(socket.getOutputStream())) ;
		bw2.write("文件复制完毕");
		bw2.newLine();
		bw2.flush();
		
		//关闭
		bw.close();
		socket.close();
	}
}

8.客户端–服务端<–>图片复制读写(反馈信息)

8.1)客户端的一个图片文件:当前项目下xxx.jpg,写入通道流中

package com.qianfeng.tcp_09;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

/**
 * 图片的复制:BufferedInputStream/BufferedOutputStream  
 * 
 * 一次读取一个字节数组
 * 客户端的一个图片文件:当前项目下xxx.jpg
 * 服务器端将图片文件:进行复制:mv.jpg
 * 
 * 加入服务器端的反馈
 * 
 * 发现问题:
 * 		图片文件:没有复制完整,图片文件缺失(少字节数)
 * 图片文件本身在内存中:缓存数据!
 * 
 * 字节缓冲输出流中:public void flush():强制将缓冲的字节数输出到流中!
 * 
 * @author zhangyang
 *
 */
public class UploadImageClient {
	
	public static void main(String[] args) throws IOException {
		
		//创建Scoket
		Socket s = new Socket("10.12.156.36",6666) ;
		
		//创建字节输入流:封装图片文件
		BufferedInputStream bis = 
				new BufferedInputStream(new FileInputStream("高圆圆.jpg")) ;
		//封装通过的字节输出流
		BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream()) ;
		
		//一次读取一个字节数组
		byte[] bytes = new byte[1024] ;
		int len = 0 ;
		while((len=bis.read(bytes))!=-1) {
			bos.write(bytes, 0, len);
			
			//刷新
			bos.flush();
		}
		
		//告诉服务器端,图片文件已经全部写入到输出流中,不要等待了
		s.shutdownOutput();
		
		
		//读取服务端反馈数据
		//获取通道内的字节输入流
		InputStream in = s.getInputStream() ;
		//一次读取一个字节数组
		byte[] bytes2 = new byte[1024] ;
		int len2 = in.read(bytes2) ;
		String fkMsg = new String(bytes2, 0, len2) ;
		System.out.println("fkMsg:"+fkMsg);
		
		//释放资源
		
		bis.close();
		
		s.close();
	}

}


8.2)服务器端读取通道流中的图片,将图片文件:进行复制:mv.jpg

package com.qianfeng.tcp_09;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class UploadImageServer {
	
	public static void main(String[] args) throws IOException {
		
		ServerSocket ss = new ServerSocket(6666) ;
		
		Socket socket = ss.accept() ;
		
		//封装通道内在字节输入流
		BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()) ;
		//输出到指定文件
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("mv.jpg")) ;
		
		//一次读取一个字节数组
		byte[] bytes = new byte[1024] ;
		int len = 0  ;
		while((len = bis.read(bytes))!=-1) {
			//写入
			bos.write(bytes, 0, len);
			
			//强制刷新
			bos.flush();
		}
		
		//加入反馈
		//获取通道内的输出流
		OutputStream out = socket.getOutputStream() ;
		out.write("图片已经复制完毕".getBytes());
		//刷新
		out.flush();
		
		
		//释放资源
		bos.close();
		socket.close();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值