网络编程学习笔记

本文深入探讨了TCP和UDP两种网络传输协议,详细解析了它们的工作原理和适用场景。通过实例展示了TCP服务器和客户端的交互过程,包括创建Socket、数据传输和关闭连接。同时,介绍了UDP的不可靠、无需连接特性,以及发送和接收数据报包的实现。文章还涵盖了基于TCP和UDP的文件传输、聊天应用和多线程编程的应用案例。

网络编程

public class Demo01TCP_Client {
    /*socket:网络编程: 在网络之间 实现不同计算机之间的数据传输
     * 
     *ip:互联网上每台计算机的唯一标识
     *   ---ipv4:4个1byte组成:    192.168.2.110
     *   ---ipv6:8个2byte组成 16进制表示:  cccc.cccc.8889.af89.1111.121a.1111.a001
     *域名:给ip对应的方便记忆的字符串   
     *本地ip:127.0.0.1    localhost  
     *port:电脑上安装的每个软件都会分配一个唯一的编号:0-65535
     *     10000以下的被分配给操作系统
     *网络传输协议:  计算机网络中实现通信必须有一些约定即通信协议,对速率、传输代码、代码结构、传 输控制步骤、出错控制等制定标准。
     *
     *TCP: transimission control protocol: (打固定电话)
     *     可控的 端对端的 字节流传输协议
     *     主要类:Socket+ServerSocket
     *     
     *     
     *UDP: user datagram protocol :(发报机)
     *     不可靠的 无需连接的 报文流传输协议
     *     主要类:DatagramSocket+DatagramPackage
     *         
     *TCP:
     *   服务器:部署项目的主机
     *   客户: 访问服务器资源的互联网用户
     *   
     *   服务器端:
     *      1 创建一个serversocket并指定一个端口------架了一个固定电话 还买了一个电话号
     *      2 等待客户端的连接----等待别人给我打电话
     *      3 获取socket的输入流和输出流 进行数据传输        ----接电话 进行停和说
     *      4 关闭服务serversocket----挂断电话
     *   客户端:
     *      1 创建一个socket指定服务器端的ip和端口---- 给服务器之间拉一个电话线
     *              socket---套接字---传输通道
     *      2 获取socket的输入流和输出流 进行数据传输        ----拨通电话 进行听和说       
     *      3 关闭socket----剪断电话线
     * */

TCP

服务器:部署项目的主机

客户:访问服务器资源的互联网用户

tcp 步骤:

服务器端

1.创建一个ServerSocket 并指定一个端口——架了一个固定电话 还买了一个电话号

2.等待客户端的连接–等待别人打电话

3.获取socket 的 输入、输出流,进行数据传输—接电话 进行听和说

4.关闭服务ServerSocket —挂断电话

代码:

		  ServerSocket server=new ServerSocket(10086);//指定要开启那个端口 来接受客户端的信息
//	     *      2 等待客户端的连接----等待别人给我打电话
		  System.out.println("服务器端等待连接---");
		  Socket   socket=server.accept();//等待并获取客户端连接--阻塞方法
//	     *      3 获取socket的输入流和输出流 进行数据传输        ----接电话 进行停和说
		  InputStream in=socket.getInputStream();
		  OutputStream out=socket.getOutputStream();
		  out.write("hello 谁啊?".getBytes());//服务器先说话:
		  byte[] arr=new byte[1024];//接受客户端回应
		  int n=in.read(arr);
		  System.out.println("客户端的回答是:"+new String(arr,0,n));
		  out.write("不认识 打错了!".getBytes());
//	     *      4 关闭服务serversocket----挂断电话
          server.close();
        
}

客户端

1.创建一个socket指定服务器的端口和ip----给服务器之间拉一个电话线

socket:–套接字–传输通道

2.获取socket的输入流和输出流 进行数据传输 -----拨通电话 进行听和说

3.关闭socket ----剪断电话线

代码:

//		     *       1 创建一个socket指定服务器端的ip和端口---- 给服务器之间拉一个电话线
//		     *              socket---套接字---传输通道
		Socket socket=new Socket("127.0.0.1", 10086);
//		     *      2 获取socket的输入流和输出流 进行数据传输        ----拨通电话 进行听和说       
		InputStream in=socket.getInputStream();
		OutputStream out=socket.getOutputStream();
		byte[] arr=new byte[1024];
		int n=in.read(arr);
		System.out.println("服务器端说:"+new String(arr,0,n));
		out.write("我是苗天宝,找你借点钱!".getBytes());
		n=in.read(arr);
		System.out.println("服务器端说:"+new String(arr,0,n));
//		     *      3 关闭socket----剪断电话线
		socket.close();
	}

让服务器端对客户端发送的数据进行转换 删除数组 大写转小写 小写转换为大写

Client

//1 创建socket:指定服务器端的ip和服务器端开启的端口
	Socket socket=new Socket("127.0.0.1", 10086);
	 String localIp=socket.getLocalAddress().getHostName();
	 int localPort=socket.getLocalPort();
	 String ip=socket.getInetAddress().getHostName();
	 int port=socket.getPort();
	 System.out.println("客户端::::localIp="+localIp+":::localPort="+localPort);
	 System.out.println("客户端::::ip="+ip+":::port="+port);
	//2 获取输入流和输出流
	InputStream in=socket.getInputStream();
	OutputStream out=socket.getOutputStream();
	//3接受和发送信息
	//获取键盘输入的信息
	BufferedReader bin=new BufferedReader(new InputStreamReader(System.in));
	while(true) {
		System.out.println("请输入一行数据:如果要结束 请输入886");
		String line=bin.readLine();
		out.write(line.getBytes());//通过socket的输出流把读取的信息发出去
		byte[] arr=new byte[1024];
		int n=in.read(arr);//接受服务器端的信息
		String message=new String(arr, 0,n);
		System.out.println("客户端接受到的信息是:"+message);
		if(line.contains("886")) {
			break;
		}
	}
	
	//4关闭socket
	socket.close();

}

server

 //1 创建服务
	 ServerSocket server=new ServerSocket(10086);//开启的端口是10086 此端口可以给客户端进行数据传输
	 //2 等待连接 获取socket:传输通道
	 System.out.println("服务器端开启端口10086开始服务::::");
	 Socket socket=server.accept();//阻塞方法:等待客户端连接 
	 String localIp=socket.getLocalAddress().getHostName();
	 int localPort=socket.getLocalPort();
	 String ip=socket.getInetAddress().getHostName();
	 int port=socket.getPort();
	 System.out.println("服务器端::::localIp="+localIp+":::localPort="+localPort);
	 System.out.println("服务器端::::ip="+ip+":::port="+port);
	 //3 从传输通道中获取输入流和输出流
	 InputStream in=socket.getInputStream();
	 OutputStream out=socket.getOutputStream();
	 //4 通过输入流和输出流发送信息
	 while(true) {
		 byte[] arr=new byte[1024];
		 int n=in.read(arr);
		 String message=new String(arr, 0, n);
		 System.out.println("接收到客户端信息:"+message);
		 String messageNew=change(message);//字符串转换
		 out.write(messageNew.getBytes());
		 if(message.contains("886")) {
			 break;
		 }
	 }
	 //5关闭服务
	 server.close();

}
private static String change(String s) {
	StringBuffer stb=new StringBuffer(s);
	for (int i = 0; i < stb.length(); i++) {
		char c=stb.charAt(i);
		if(Character.isUpperCase(c)) {
			stb.setCharAt(i, Character.toLowerCase(c));
		}else if(Character.isLowerCase(c)) {
			stb.setCharAt(i, Character.toUpperCase(c));
		}else if(Character.isDigit(c)) {
			stb.deleteCharAt(i);
			i--;
		}
	}
	return stb.toString();
}

通过tcp实现文件上传

client:

	/*1 创建一个流与源文件关联
	 *2 创建socket与服务器端连接
	 *3 通过socket的输出流把文件的名字传递给服务器端
	 *4 通过socket的输出流把文件中的信息传递给服务器端
	 *5读到末尾 就上传完毕  关闭socket
	 * */
	//创建流与源文件关联
	 File file=new File("src\\test\\1.jpg");
	 FileInputStream fin=new FileInputStream(file);
	 //创建socket指定服务器的ip和端口
	 Socket socket=new Socket("localhost", 10010);
	 //获取输出流
	 OutputStream out=socket.getOutputStream();
	 //把文件民写出去
	 out.write(file.getName().getBytes());
	 //一边读文件 一边通过sockct发送信息给服务器
	 byte[] arr=new byte[1024];
	 int n;
	 while((n=fin.read(arr))!=-1) {
		out.write(arr, 0, n);
	 }
	 
	 socket.shutdownOutput();//关闭输出流
	 //获取输入流来获取服务器端的反馈
	 InputStream in=socket.getInputStream();
	 n=in.read(arr);
	 System.out.println("接收到服务器端的信息是:"+new String(arr, 0,n));
	 //关闭socket
	 socket.close();

server:

	//创建服务
	ServerSocket server=new ServerSocket(10010);
	//获取连接
	Socket socket=server.accept();
	//获取输入流
	InputStream sin=socket.getInputStream();
	//获取文件名字
	byte[] arr=new byte[1024];
	int n=sin.read(arr);
	String fileName=new String(arr, 0,n);
	//1 创建文件输出流与目的文件关联
	FileOutputStream fout=new FileOutputStream("d:\\"+fileName);
	//一边从socket中读信息 一边把信息写到目的文件中
	while((n=sin.read(arr))!=-1) {
		fout.write(arr, 0, n);
	}
	//给客户端发送反馈信息
	OutputStream  sout=socket.getOutputStream();
	sout.write(("接受文件"+fileName+"成功!").getBytes());
	//关闭服务
	server.close();
}

聊天(使用线程):

client

public class Demo04Chat_Client {

	public static void main(String[] args)throws Exception {
		//获取键盘的信息 发给服务器端
		BufferedReader bin=new BufferedReader(new InputStreamReader(System.in));
		//创建socket 指定服务器端的ip和端口
		Socket socket=new Socket("192.168.217.32", 10086);
		//获取socket的输出流和输出流
		InputStream in=socket.getInputStream();
		OutputStream out=socket.getOutputStream();
		//为了实现收发同步  需要创建两个线程 分别来控制输入流和输出流
	    new InThreadClient(in).start();
	    new OutThreadClient(out,bin).start();
	    
	}

}
class InThreadClient extends Thread{
	InputStream in;
	InThreadClient(InputStream in) {this.in=in;}
	public void run() {
		try {
			byte[] arr=new byte[1024];
			int n;
			while((n=in.read(arr))!=-1) {
				System.out.println(new String(arr, 0, n));
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}
class OutThreadClient extends Thread{
	OutputStream out;
	BufferedReader bin;
	OutThreadClient(OutputStream out,BufferedReader bin) {this.out=out;this.bin=bin;}
	public void run() {
		try {
			String line;
			while((line=bin.readLine())!=null) {
				out.write(line.getBytes());
				if(line.contains("886")) {
					break;
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

server

public class Demo04Chat_Server {
    // 创建s
	public static void main(String[] args) throws Exception{
		// 1 创建serversocket
		ServerSocket ss=new ServerSocket(10086);
		// 2 获取socket
		HashSet<OutputStream> set=new HashSet<>();
		while(true) {
			Socket socket=ss.accept();
			set.add(socket.getOutputStream());
			new InOutThread(socket,set).start();
		}

	}

}
class InOutThread extends Thread{
	Socket socket;
	HashSet<OutputStream> set;
	InOutThread(Socket socket,HashSet<OutputStream> set){
		this.socket=socket;
		this.set=set;
	}
	public void run() {
		String ip_port=socket.getInetAddress().getHostName()+"_"+socket.getPort()+"说:";
		try {
			InputStream in=socket.getInputStream();
			byte[] arr=new byte[1024];
			int n;
			while((n=in.read(arr))!=-1) {
				String message=new String(arr, 0, n);
				for (OutputStream out : set) {
					out.write((ip_port+message).getBytes());
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

文件复制

 //服务器端
	 ServerSocket ss=new ServerScoket(10086);//创建服务
	 Socket socket=ss.accept();//等待连接
	 InputStream in=socket.getInputStream();
	 byte[] arr=new byte[1024]; int n;
	 n=in.read(arr);//先获取文件名字
	 String fileName=new String(arr,0,n);
	 //创建输出流与目的文件关联
	 BufferedOutputStream bout=new BufferedOutputStream(new FileOutputStream(fileName));
	 //一边从socket中读取信息 一般把信息写到目的文件中
	 while((n=in.read(arr))!=-1){
	     bout.write(arr,0.n);
		 bout.flush();
	 }
	 //给客户端反馈
	 OutputStream out=socket.getOutputStream();
	 out.write(("接受"+fileName+"成功").getBytes());
	 //关闭服务
	 bout.close();
	 ss.close();
	 
	 
	 //客户端:
	 File file=new File("d:\\1.jpg");
	 Socket socket=new Socket("127.0.0.1",10086);
	 OutputStream out=socket.getOutputStream();
	 out.write(file.getName().getBytes());//先发送文件名字
	 //创建输入流与源文件关联
	 BufferedInputStream bin=new BufferedInputStream(new FileInputStream(file));
	 //边读边发
	 byte[] arr=new byte[1024]; int n;
	 while((n=bin.read(arr))!=-1){
	      out.write(arr,0,n);
	 }
	 socket.shutDownOutputStream();//关闭socket的输出流
	 //获取服务器端的反馈
	 InputStream in=socket.getInputStream();
	 n=in.read(arr);
	 System.out.println("服务器端的反馈:"+new String(arr,0,n));
	 socket.close();
	 

UDP

发送方

   /*
     * UDP:user datagram protocol
     *     不可靠的 无需连接的 报文流传输协议
     * 发送方:
     *   
     *         
     * */
	public static void main(String[] args) throws Exception{
		//1:创建udp的socket: 指定开启的端口
		DatagramSocket socket=new DatagramSocket(10086);
        //2:创建一个datagrampackage封装要发送的信息
		byte[] arr="你好吗udp".getBytes();
		DatagramPacket sendPacket=new DatagramPacket(arr, 0, arr.length, InetAddress.getByName("127.0.0.1"), 10010);
		//参数解释:arr:要发送的信息对应的字节数组, 0:要发送的字节从哪里开始发, arr.length:要发的字节总数, 
		//       InetAddress.getByName("127.0.0.1"):接受方的ip, 10010:接受方的端口
		//DatagramPacket有6个构造方法:
		//构造方法中 需要ip和端口的用于发送
		//构造方法中 不需要ip和端口的用于接受
		//3 通过socket把数据报包发出去
		socket.send(sendPacket);
		//4 关闭socket
		socket.close();
	}

接收方

/*
     * UDP:user datagram protocol
     *     不可靠的 无需连接的 报文流传输协议
     *接收方
     *   
     *         
     * */
	public static void main(String[] args) throws Exception{
		//接收方:
		//1 创建一个udp的socket:并指定要开启的端口
		DatagramSocket socket=new DatagramSocket(10010);
		//2 创建一个空的datagarampacket来接受信息
		byte[] arr=new byte[1024];//定义一个字节数组 装信息
		DatagramPacket receivePacket=new DatagramPacket(arr, arr.length);
		//3接受信息
		socket.receive(receivePacket);//使用空的DatagramPacket来接受信息:信息存放到arr中
		//从数组中解析信息
		//receivePacket.getLength();//获取接受的有效信息字节数
		int length=receivePacket.getLength();
		System.out.println("10010接受到的信息是:"+new String(arr, 0, length));
		System.out.println("getAddress:"+receivePacket.getAddress().getHostName());
		System.out.println("getPort:"+receivePacket.getPort());
		//4 关闭socket
		socket.close();
		

聊天(使用线程)

public class Demo07UDP {

	public static void main(String[] args)throws Exception {
		startUDP(10010,10086,"192.168.217.255");
	}
	public static void startUDP(int myPort,int port,String ip)throws Exception {
		//创建一个socket
		DatagramSocket socket=new DatagramSocket(myPort);
		System.out.println(myPort+"开始聊天。。。。");
		//一个线程只管发送 
		new SendThread(socket, port, ip).start();;
		//一个线程只管接受
		new ReceiveThread(socket).start();;
	}


}
class SendThread extends Thread{
	DatagramSocket socket;
	int port;String ip;
	SendThread(DatagramSocket socket,int port,String ip){this.socket=socket;this.port=port;this.ip=ip;}
	public void run() {
		//获取键盘输入流
		BufferedReader bin=new BufferedReader(new InputStreamReader(System.in));
		String line;
		try {
			while(true) {
				line=bin.readLine();
				byte[] arr=line.getBytes();
				DatagramPacket sendPacket=new DatagramPacket(arr, arr.length, InetAddress.getByName(ip), port);
				socket.send(sendPacket);
				if(line.contains("886")) {
					break;
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}finally {
			socket.close();
		}
	}
}
class ReceiveThread extends Thread{
	DatagramSocket socket;
	ReceiveThread(DatagramSocket socket){this.socket=socket;}
	public void run() {
		byte[] arr=new byte[1024];
		try {
			while(true) {
				DatagramPacket receivePacket=new DatagramPacket(arr, 0, arr.length);
				socket.receive(receivePacket);
				//数据解析
				String message=new String(arr,0,receivePacket.getLength());
				String ip_port=receivePacket.getAddress().getHostName()+"_"+receivePacket.getPort();
				System.out.println(socket.getLocalPort()+"接收到"+ip_port+"的信息:"+message);
				if(message.contains("886")) {
					break;
				}
			}
		} catch (SocketException e) {
			System.out.println(socket.getLocalPort()+"结束聊天!!!");
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}


//1 互发信息

public class Demo06UDP_2 {
    //先收 后发
	public static void main(String[] args) throws Exception{
		BufferedReader bin=new BufferedReader(new InputStreamReader(System.in));
		//1 创建datagramsocket指定要开启的端口
		DatagramSocket socket=new DatagramSocket(10086);
		//2 创建一个datagrampacket用于发送信息
		while(true) {
			//创建一个空的datagrampakcet用于接受信息
			byte[] arr=new byte[1024];
			DatagramPacket receivePacket=new DatagramPacket(arr, arr.length);
			socket.receive(receivePacket);
			//解析信息
			String message=new String(arr, 0,receivePacket.getLength());
			System.out.println("10010接受到10086的信息是:"+message);
			

			String line=bin.readLine();//从键盘读取一行信息
			arr=line.getBytes();
			//把读取的信息通过udp发送出去
			DatagramPacket sendPacket=new DatagramPacket(arr, arr.length, InetAddress.getByName("localhost"), 10010);
			socket.send(sendPacket);
			
			if(line.contains("886")||message.contains("886")) {
				break;
			}
		}
		//关闭socket
		socket.close();
	
	}

}
public class Demo06UDP_1 {

	public static void main(String[] args) throws Exception{
		BufferedReader bin=new BufferedReader(new InputStreamReader(System.in));
		//1 创建datagramsocket指定要开启的端口
		DatagramSocket socket=new DatagramSocket(10010);
		//2 创建一个datagrampacket用于发送信息
		
		while(true) {
			String line=bin.readLine();//从键盘读取一行信息
			byte[] arr=line.getBytes();
			//把读取的信息通过udp发送出去
			DatagramPacket sendPacket=new DatagramPacket(arr, arr.length, InetAddress.getByName("localhost"), 10086);
			socket.send(sendPacket);
			//创建一个空的datagrampakcet用于接受信息
			arr=new byte[1024];
			DatagramPacket receivePacket=new DatagramPacket(arr, arr.length);
			socket.receive(receivePacket);
			//解析信息
			String message=new String(arr, 0,receivePacket.getLength());
			System.out.println("10010接受到10086的信息是:"+message);
			if(line.contains("886")||message.contains("886")) {
				break;
			}
		}
		//关闭socket
		socket.close();
	
	}

}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值