网络通讯(TCP和UDP)和网络聊天室and传输文件

先展示一套简单的网络通信代码

/*
 * 客户端建立思路:
 * 		1.创建TCP客户端socket服务,使用的是socket对象
 * 		2.如果连接成功,说明数据传输通过建立
 * 		通过就是socket流,是底层建立好的
 * 		是流就应该由输入和输入。
 * 		想要获取输入或者输入流对象,可以找socket获取
 * 		可以通过getOutputStream()和getInputStream()来获取两个字节流
 * 		3.使用输入流吗,将数据写入。
 * 		4.关闭资源
 */
public class Client {
	public static void main(String[] args) {
		try {
//		Socket(String host,int port);
			//1.创建Socket对象,指定服务器的IP地址和端口号
			Socket s = new Socket("localhost", 8888);
			//建立连接后,通过socket中的IO流进行数据传输
			//向服务器发送   你好,服务器
			//如果想要使用字符流 需要使用OutputStreamWriter/InputStreamWriter 转换流
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
			bw.write("你好,服务器");
			bw.flush();
			
			s.shutdownOutput();
			
			BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
			String str = br.readLine();
			System.out.println("服务器端发来的消息是:"+str);
			
			s.close();
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

/*
 * 建立TCP服务器端思路:
 * 		1.创建服务器socket服务。通过ServerSocket对象
 * 		2.服务器端必须对外提供一个端口,否则客户端无法连接
 * 		3.获取连接过来的客户端对象
 * 		4.通过客户端对象获取socket流读取客户端发来的数据打印
 * 		5.关闭资源、关闭流、关闭服务器
 * 		
 */
public class Server {
	public static void main(String[] args) {
		try {
			//1.创建ServerSocket类型的对象,指定接口
			ServerSocket ss = new ServerSocket(8888);
			System.out.println("等待客户端连接....");
			//等待客户端连接,使用accept()
			Socket s = ss.accept();//进行阻塞
			System.out.println("客户端连接成功....");
			
			//使用字符缓冲输入流接收客户端消息
			BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
			String str = br.readLine();
			System.out.println("客户端发来的消息是:"+str);
			
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
			bw.write("客户端你好呀!");
			bw.newLine();

			bw.close();
			br.close();
			s.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

java生下来一开始就是为了计算机之间的通信,因此这篇文章也将开始介绍一下java使用socket进行计算机之间的通信,在上一篇文章中已经对网络通信方面的基础知识进行了总结,这篇文章将通过代码案例来解释说明。

一、网络编程基础

因为java网络编程这块是从基础开始讲解的,所以知识点也是由浅入深,因此还是有必要对一些基础的知识进行回顾和掌握,如果你是大神,不喜勿喷。

1、两台计算机之间的通信

两台计算机如何实现通信呢?人类交流是通过定义一定的语言,计算机也是,他们之间必须要有相应的协议才可以。
在这里插入图片描述

也就是说,两台计算机要想通信必须要遵循一定的规则协议。通信流程基本上就是,一台计算机上的一个端口号数据,然后通过协议发送到另外一台计算机上的同一个端口号。这里面有三个重要的部分需要我们去理解一下,当然不会细讲,因为在上一篇文章中已经提出。

(1)TCP/IP协议

(2)IP地址

(3)端口

我们先讲一下TCP/IP模型。

2、TCP/IP模型

TCP/IP模型就是上面的协议,它定义了一些规则来用于计算机之间的通信,同时也是世界上应用最为广泛的协议。这个协议模型建立在TCP和IP协议上面(从名字也可以看出来)。
在这里插入图片描述

从上图我们可以看到TCP/IP其实是处于传输层的,也就是我们的协议核心所在,TCP/IP协议定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。

3、IP地址

为了实现两个网络中不同计算机之间的通信,每台计算机都必须有一个唯一的标识,就是中国公民每一个人都有一个惟一的身份证号码一样。

4、端口

我们知道一台计算机其实是可以跑很多个程序的,那么我们的程序怎么就能准确无误的到达另外一个程序呢?这其实就是使用了端口号来区分不同的应用程序。

端口号的范围也很大0到65535。其中0到1023是保留的,也就是我们不能用的。那我们的今天所讲的socket是如何组成的呢?其实就是由IP地址和端口号组成的。

二、socket通信

在上面其实我们对通讯需要掌握的一些基础知识进行了分析,这里我们开始使用java语言来演示一下这个过程。

socket通信其实是有两种方式:TCP和UDP过程。

(1)TCP是可靠地面向连接的通信过程,含有三次握手四次挥手的机制。

(2)UDP是不可靠的无连接的通信过程,客户端只管发,不管服务端有没有接受到。

那这两种通信方式的基本模型是什么呢?我们使用一张图来看一下:、
在这里插入图片描述

从上图我们可以看到,Socket实现的步骤大体包含以下几个步骤:

(1)创建Server和client的ServerSocket和Socket。

(2)打开链接到Socket的输入输出流

(3)按照协议对Socket进行读取操作

(4)关闭输入输出流、关闭Socket。

下面我们就直接来看例子,然后再来分析这个例子:

1、基于TCP的socket通信

我们拿男孩做客户端,女孩因为有很多人追求,所以做服务端,一个服务端可被多个男孩客户端请求表白。我们这里先看女孩服务端的具体步骤:

(1)创建ServerSocket对象,绑定监听端口。

(2)通过accept()方法监听客户端请求

(3)连接建立后,通过输入流读取客户端的数据

(4)通过输出流,向客户端回应信息

下面是一套传输文件的

public class Server {
	public static void main(String[] args) {
		try {
			ServerSocket ss = new ServerSocket(8888);
			System.out.println("等待客户端上传文件。");
			Socket s = ss.accept();
			InputStream is = s.getInputStream();
			//创建字节输出流向指定服务器中输入用户上传的文件
			BufferedOutputStream bos = new BufferedOutputStream(new     FileOutputStream("5.jpg"));
			
			byte[] by =new byte[1024*8];
			BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
			int num = 0;
			while((num = bis.read())!= -1){
				bos.write(by, 0, num);
				bos.flush();
			}
			bos.close();
			bis.close();
			s.close();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

public class Client {
	public static void main(String[] args) {
		
		try {
			Socket s = new Socket("localhost",8888);
			//读取本地文件
			BufferedInputStream bis = new BufferedInputStream(new FileInputStream("e://4.jpg"));
			BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream()); 
			//创建缓冲去
			byte[] by = new byte[1204*8];
			int num = 0;
			//读取本地文件
			while((num = bis.read())!=-1){
				//将本地读取的数据写入指定服务器
				bos.write(by,0,num);
				bos.flush();
			}
			bos.close();
			bis.close();
			s.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}

下面是获取ip地址等

//1.获取本机的主机地址和IP地址信息
		try {
			InetAddress ia = InetAddress.getLocalHost();
			//自动调用toString(); 字符串的格式:主机名/IP地址
			System.out.println(ia);//LAPTOP-QOPMUIA9/127.0.0.1
			//拆分地址信息分别获取主机名和IP地址  分别打印
			System.out.println(ia.getHostName());//LAPTOP-QOPMUIA9
			System.out.println(ia.getHostAddress());//127.0.0.1
				
			//2.获取指定主机名中的地址信息
			InetAddress ia2 = InetAddress.getByName("LAPTOP-QOPMUIA9");
			System.out.println(ia2);
			System.out.println(ia2.getHostName());
			System.out.println(ia2.getHostAddress());

		} catch (UnknownHostException e) {
			e.printStackTrace();
		}

下面是一套类似聊天室的代码

	public static void main(String[] args) {
		try {
			Socket socket = new Socket("localhost", 8099);

			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

			BufferedReader br2 = new BufferedReader(new InputStreamReader(socket.getInputStream()));

			PrintStream printStream = new PrintStream(socket.getOutputStream());

			while (true) {
				System.out.println("请输入要发送的内容~!");
				String readLine = br.readLine();
				printStream.println(readLine);
				System.out.println("客户端已发送,内容是:" + readLine);
				String readLine2 = br2.readLine();
//				大小写铭感的问题
				if (readLine2.equalsIgnoreCase("by")) {
					break;
				}

				System.out.println("服务器端说:" + readLine2);
			}

			br2.close();
			br.close();
			printStream.close();
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

服务器

public class ServerThread extends Thread {
	private Socket socket;
	public ServerThread(Socket socket) {
		this.socket = socket;
	}
	@Override
	public void run() {
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			PrintStream printStream = new PrintStream(socket.getOutputStream());
			while (true) {
				String readLine = br.readLine();

				if (readLine.equalsIgnoreCase("by")) {
					break;
				}
				printStream.println(readLine);

				System.out.println(socket.getInetAddress() + "客户端说的是" + readLine);
				printStream.print("我是服务端");
				System.out.println("服务器已经发送");

			}
			br.close();
			printStream.close();
			socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


public class ServerTest {
	public static void main(String[] args) {
		try {
			ServerSocket serverSocket = new ServerSocket(8099);

			while (true) {
				System.out.println("等待客户端连接");
				Socket socket = serverSocket.accept();
				System.out.println("来了一个" + socket.getInetAddress());
				new ServerThread(socket).start();
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}

基于UDP的Socket通信

UDP的通信模式其实是无连接的不可靠的通信协议,举个例子,不管对方有没有收到信息,自己继续像其他发送信息。

我们首先来看一下服务端的步骤:

接收客户端发送的数据

(1)创建服务器端DatagramSocket指定端口

(2)创建数据报DatagramPacket,接收客户端发送的数据

(3)接收客户端发送的数据

(4)读取数据

向客户端响应数据

(1)定义客户端的地址、端口号、数据

(2)创建数据报,包含响应的数据信息

(3)响应客户端

(4)关闭资源

public class TestReceive {
	public static void main(String[] args) throws Exception {
		//1.创建DatagramSocket类型的对象,并提供端口号
		DatagramSocket ds = new DatagramSocket(8888);
		//2.创建DatagramPacket类型的对象,用于接收数据内容
		byte[] data = new byte[1024];
		DatagramPacket dp = new DatagramPacket(data, data.length);
		
		//3.接收数据并保存到数据报中,使用receive()方法
		ds.receive(dp);
		
		System.out.println("接收到的数据是:"+new String(data,0,dp.getLength())+"!");
		//4.关闭套接字
		ds.close();
	}
}
public class TestSend {
	public static void main(String[] args) throws Exception {
		// 1.创建DatagramSocket类型的对象
		DatagramSocket ds = new DatagramSocket();

		// 2.创建DatagramPacket类型的对象,提供接收方的端口号和IP地址
		byte[] data = "hello".getBytes();

		InetAddress ia = InetAddress.getLocalHost();
		DatagramPacket dp = new DatagramPacket(data, data.length, ia, 8888);
		// 3.发送数据内容,使用send()方法
		ds.send(dp);
		System.out.println("成功发送数据内容");
		// 4.关闭套接字
		ds.close();
	}
}
发布了51 篇原创文章 · 获赞 172 · 访问量 2882

猜你喜欢

转载自blog.csdn.net/weixin_45519387/article/details/103993639