Java网络编程—TCP

TCP传输协议:一种面向连接(连接导向)的、可靠的、基于字节流的运输层通信协议

特点:
  面向连接、
  点到点的通信、
  高可靠性、
  占用系统资源多、效率低

三次握手:点名、答到、确认
在这里插入图片描述
在这里插入图片描述

TCP 熟悉流程 代码示例

代码示例:

/*
 * 熟悉流程
 * 创建服务器
 * 1、指定端口  使用ServerSocket 创建服务器
 * 2、阻塞式等待连接  accept()
 * 3、操作:输入输出流操作
 * 4、释放资源
 * 
 */

public class Server {

	public static void main(String[] args) throws IOException {
		System.out.println("-----Server-----");
		// 1、指定端口  使用ServerSocket 创建服务器
		ServerSocket server = new ServerSocket(9999);
		// 2、阻塞式等待连接  accept()
		Socket client = server.accept();
		// 一个 accept() 就为一个连接
		System.out.println("一个客户端建立了连接");
		
		// 3、操作:输入输出流操作
		// 服务端的输人流:client.getInputStream()  相当于管道
		DataInputStream dis =new DataInputStream(client.getInputStream());
		String data = dis.readUTF();
		System.out.println(data);
		// 4、释放资源
		dis.close();
		client.close();
		// 一般服务器不关闭的,除非要维护
		server.close();
	}
}
/*
 * 熟悉流程
 * 创建客户端
 * 1、建立连接:使用 Socket 创建客户端 + 服务器的地址和端口
 * 2、操作:输入输出流操作
 * 3、释放资源
 * 
 */
public class Client {

	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("-----Client-----");
		// 1、建立连接:使用 Socket 创建客户端 + 服务器的地址和端口
		Socket client = new Socket("localhost",9999);
		// 2、操作:输入输出流操作
		// 客户端说一个你好,对于客户端来说是输出流
		// 客户端的输出流:client.getOutputStream()
		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
		String data = "hello";
		dos.writeUTF(data); 
		dos.flush();
		// 3、释放资源
		dos.close();
		client.close();
	}
}

TCP 文件的上传和存储 代码示例

代码示例:

/*	
 * 存储文件
 * 创建服务器
 * 1、指定端口  使用ServerSocket 创建服务器
 * 2、阻塞式等待连接  accept()
 * 3、操作:输入输出流操作
 * 4、释放资源
 * 
 */

public class FileServer {

	public static void main(String[] args) throws IOException {
		System.out.println("-----Server-----");
		// 1、指定端口 使用ServerSocket 创建服务器
		ServerSocket server = new ServerSocket(9999);
		// 2、阻塞式等待连接 accept()
		Socket client = server.accept();
		// 一个 accept() 就为一个连接
		System.out.println("一个客户端建立了连接");
		// 3、操作:文件的拷贝 文件的存储 (相当于先把文件读取进来)
		// 服务端的输人流:client.getInputStream() 相当于管道,接收客户端的 输出流
		InputStream is = new BufferedInputStream(client.getInputStream());
		// 文件拷贝到那个位置
		OutputStream os = new BufferedOutputStream(new FileOutputStream("src/tcp.png"));
		byte[] flush = new byte[1024];
		int len = -1;
		while ((len = is.read(flush)) != -1) {
			os.write(flush, 0, len);
		}
		os.flush();
		// 3、释放资源
		os.close();
		is.close();
		// 4、释放资源
		client.close();

		// 一般服务器不关闭的,除非要维护
		server.close();
	}
}
/*
 * 上传文件
 * 创建客户端
 * 1、建立连接:使用 Socket 创建客户端 + 服务器的地址和端口
 * 2、操作:输入输出流操作
 * 3、释放资源
 *  
 */
public class FileClient {

	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("-----Client-----");
		// 1、建立连接:使用 Socket 创建客户端 + 服务器的地址和端口
		Socket client = new Socket("localhost", 9999);
		// 2、操作:文件的拷贝 文件上传 (相当于先把文件读取进来)
		// 先把文件读取进来
		InputStream is = new BufferedInputStream(new FileInputStream(
				"E:/gongfang/JavaDemo/linweimao/javaWork/Demo/Net_study02/src/com/lwm/tcp/file/p.png"));
		// 客户端的输出流:client.getOutputStream() 相当于管道,发送给服务端的接收流
		OutputStream os = new BufferedOutputStream(client.getOutputStream());
		byte[] flush = new byte[1024];
		int len = -1;
		while ((len = is.read(flush)) != -1) {
			os.write(flush, 0, len);
		}
		os.flush();
		// 3、释放资源
		os.close();
		is.close();
		client.close();
	}
}

在这里插入图片描述

TCP 模拟登录:双向 代码示例

代码示例:

/*
 * 模拟登录  双向
 * 创建服务器
 * 1、指定端口  使用ServerSocket 创建服务器
 * 2、阻塞式等待连接  accept()
 * 3、操作:输入输出流操作
 * 4、释放资源
 *  
 */

public class LoginTwoWayServer {

	public static void main(String[] args) throws IOException {
		System.out.println("-----Server-----");
		// 1、指定端口 使用ServerSocket 创建服务器
		ServerSocket server = new ServerSocket(9999);
		// 2、阻塞式等待连接 accept()
		Socket client = server.accept();
		// 一个 accept() 就为一个连接
		System.out.println("一个客户端建立了连接");

		// 3、操作:输入输出流操作
		// 服务端的输人流:client.getInputStream()  相当于管道
		DataInputStream dis = new DataInputStream(client.getInputStream());
		String datas = dis.readUTF();
		String uname = "";
		String upwd = "";
		// 分析
		String[] dataArray = datas.split("&");
		for (String info : dataArray) {
			String[] userInfo = info.split("=");
			if (userInfo[0].equals("uname")) {
				System.out.println("你的用户名为:" + userInfo[1]);
				uname = userInfo[1];
			} else if (userInfo[0].equals("upwd")) {
				System.out.println("你的密码为:" + userInfo[1]);
				upwd = userInfo[1];
			}
		}
		// 输出
		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
		if (uname.equals("lwm") && upwd.equals("123456")) { // 成功
			dos.writeUTF("登录成功,欢迎回来");
		} else { // 失败
			dos.writeUTF("用户名或密码错误");
		}
		dos.flush();
		// 4、释放资源 
		dis.close();
		client.close();

		// 一般服务器不关闭的,除非要维护
		server.close();
	}
}
/*
 * 模拟登录  双向
 * 创建客户端
 * 1、建立连接:使用 Socket 创建客户端 + 服务器的地址和端口
 * 2、操作:输入输出流操作
 * 3、释放资源
 * 
 */
public class LoginTwoWayClient {

	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("-----Client-----");
		BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
		System.out.print("请输入用户名:");
		String uname = console.readLine();
		System.out.print("请输入密码:"); 
		String upwd = console.readLine();
		// 1、建立连接:使用 Socket 创建客户端 + 服务器的地址和端口
		Socket client = new Socket("localhost",9999);
		// 2、操作:输入输出流操作
		// 客户端说一个你好,对于客户端来说是输出流
		// 客户端的输出流:client.getOutputStream()
		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
		dos.writeUTF("uname="+uname+"&"+"upwd="+upwd);
		dos.flush();
		
		DataInputStream dis = new DataInputStream(client.getInputStream());
		String result = dis.readUTF();
		
		System.out.println(result);
		// 3、释放资源
		dos.close();
		client.close();
	}
}

TCP 模拟登录:多个客户端请求(不用多线程,直接加while)

不用多线程,如果直接加while的话那么客户端有先后顺序,A用户完成了B用户才可以进来
代码示例:

// 如果直接加while的话那么客户端有先后顺序,A用户完成了B用户才可以进来

/*
 * 模拟登录  多个客户端请求
 * 创建服务器
 * 1、指定端口  使用ServerSocket 创建服务器
 * 2、阻塞式等待连接  accept()
 * 3、操作:输入输出流操作
 * 4、释放资源
 * 
 */

// 如果直接加while的话那么客户端有先后顺序,A用户完成了B用户才可以进来
public class LoginMultiServer {

	public static void main(String[] args) throws IOException {
		System.out.println("-----Server-----");
		// 1、指定端口 使用ServerSocket 创建服务器
		ServerSocket server = new ServerSocket(9999);
		boolean isRunning = true;
		// 2、阻塞式等待连接 accept()
		while (isRunning) {
			Socket client = server.accept();
			// 一个 accept() 就为一个连接
			System.out.println("一个客户端建立了连接");

			// 3、操作:输入输出流操作
			// 服务端的输人流:client.getInputStream() 相当于管道
			DataInputStream dis = new DataInputStream(client.getInputStream());
			String datas = dis.readUTF();
			String uname = "";
			String upwd = "";
			// 分析
			String[] dataArray = datas.split("&");
			for (String info : dataArray) {
				String[] userInfo = info.split("=");
				if (userInfo[0].equals("uname")) {
					System.out.println("你的用户名为:" + userInfo[1]);
					uname = userInfo[1];
				} else if (userInfo[0].equals("upwd")) {
					System.out.println("你的密码为:" + userInfo[1]);
					upwd = userInfo[1];
				}
			}
			// 输出
			DataOutputStream dos = new DataOutputStream(client.getOutputStream());
			if (uname.equals("lwm") && upwd.equals("123456")) { // 成功
				dos.writeUTF("登录成功,欢迎回来");
			} else { // 失败
				dos.writeUTF("用户名或密码错误");
			}
			dos.flush();
			// 4、释放资源
			dis.close();
			client.close();
		}
		// 一般服务器不关闭的,除非要维护
		server.close();
	}
}
//如果直接加while的话那么客户端有先后顺序,A用户完成了B用户才可以进来

/*
 * 模拟登录  多个客户端请求
 * 创建客户端
 * 1、建立连接:使用 Socket 创建客户端 + 服务器的地址和端口
 * 2、操作:输入输出流操作
 * 3、释放资源
 * 
 */ 

//如果直接加while的话那么客户端有先后顺序,A用户完成了B用户才可以进来
public class LoginMultiClient {

	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("-----Client-----");
		BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
		System.out.print("请输入用户名:");
		String uname = console.readLine();
		System.out.print("请输入密码:"); 
		String upwd = console.readLine();
		// 1、建立连接:使用 Socket 创建客户端 + 服务器的地址和端口
		Socket client = new Socket("localhost",9999);
		// 2、操作:输入输出流操作
		// 客户端说一个你好,对于客户端来说是输出流
		// 客户端的输出流:client.getOutputStream()
		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
		dos.writeUTF("uname="+uname+"&"+"upwd="+upwd);
		dos.flush();
		
		DataInputStream dis = new DataInputStream(client.getInputStream());
		String result = dis.readUTF();
		
		System.out.println(result);
		// 3、释放资源
		dos.close();
		client.close();
	}
}

TCP 模拟登录:多个客户端请求(使用多线程、进行代码封装)

代码示例:

//如果直接加while的话那么客户端有先后顺序,A用户完成了B用户才可以进来

/*
* 模拟登录  多个客户端请求
* 创建服务器
* 1、指定端口  使用ServerSocket 创建服务器
* 2、阻塞式等待连接  accept()
* 3、操作:输入输出流操作
* 4、释放资源
* 
*/

//如果直接加while的话那么客户端有先后顺序,A用户完成了B用户才可以进来
public class LoginMultiServer {
	
	public static void main(String[] args) throws IOException {
		System.out.println("-----Server-----");
		// 1、指定端口 使用ServerSocket 创建服务器
		ServerSocket server = new ServerSocket(9999);
		boolean isRunning = true;
		// 2、阻塞式等待连接 accept()
		while (isRunning) {
			// 2、阻塞式等待连接 accept()
			Socket client = server.accept();
			// 当客户端连接之后启动多线程,大家各自服务
			// 一个 accept() 就为一个连接
			System.out.println("一个客户端建立了连接");
			// 当客户端连接之后启动多线程,大家各自服务
			new Thread(new Channel(client)).start();
		}
		// 一般服务器不关闭的,除非要维护
		server.close();
	}

	// 内部类操作比较方便
	// 一个 Channel 就代表一个客户端
	static class Channel implements Runnable {
		private Socket client;
		// 输入流
		private DataInputStream dis;
		// 输出流
		private DataOutputStream dos;

		public Channel(Socket client) {
			this.client = client;
			// 3、操作:输入输出流操作

			try {
				// client.getInputStream()服务端的输入流,接收客户端的输出流
				// 输入流
				dis = new DataInputStream(client.getInputStream());
				// 输出流
				// 输出给客户端
				dos = new DataOutputStream(client.getOutputStream());
			} catch (IOException e) {
				e.printStackTrace();
				release();
			}
		}

		// 接收数据
		private String receive() {
			String datas = "";
			try {
				datas = dis.readUTF();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return datas;
		}

		// 释放资源
		private void release() {
			// 4、释放资源
			try {
				if (null != dos) {
					dos.close();
				}

			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if (null != dis) {
					dis.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if (null != client) {
					client.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		// 发送数据
		private void send(String msg) {
			try {
				dos.writeUTF(msg);
				dos.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}
		
		// 线程 只管业务逻辑
		@Override
		public void run() {
			// 3、操作:输入输出流操作
			// 服务端的输人流:client.getInputStream() 相当于管道
			String uname = "";
			String upwd = "";
			// 分析数据
			String[] dataArray = receive().split("&");
			for (String info : dataArray) {
				String[] userInfo = info.split("=");
				if (userInfo[0].equals("uname")) {
					System.out.println("你的用户名为:" + userInfo[1]);
					uname = userInfo[1];
				} else if (userInfo[0].equals("upwd")) {
					System.out.println("你的密码为:" + userInfo[1]);
					upwd = userInfo[1];
				}
			}
			// 进行验证返回
			if (uname.equals("123") && upwd.equals("123")) {
				// 成功
				send("登录成功,欢迎回来");
			} else {
				// 失败
				send("用户名或密码错误");
			}
			release();

		}
	}
}
//如果直接加while的话那么客户端有先后顺序,A用户完成了B用户才可以进来

/*
* 模拟登录  多个客户端请求
* 创建客户端
* 1、建立连接:使用 Socket 创建客户端 + 服务器的地址和端口
* 2、操作:输入输出流操作
* 3、释放资源
* 
*/

//如果直接加while的话那么客户端有先后顺序,A用户完成了B用户才可以进来
public class LoginMultiClient {

	public static void main(String[] args) throws UnknownHostException, IOException {
		System.out.println("-----Client-----");
		// 1、建立连接:使用 Socket 创建客户端 + 服务器的地址和端口
		Socket client = new Socket("localhost", 9999);
		// 2、操作:输入输出流操作 先请求后响应
		// 2、操作:输入输出流操作
		new Send(client).send();
		new Receive(client).receive();
		// 3、释放资源
		client.close();
	}

	// 发送
	static class Send {
		// 输出
		private DataOutputStream dos;
		private BufferedReader console;
		private Socket client;
		private String msg;
		// 客户端说一个你好,对于客户端来说是输出流
		// 客户端的输出流:client.getOutputStream()
		public Send(Socket client) {
			console = new BufferedReader(new InputStreamReader(System.in));
			this.client = client;
			this.msg = init();
			try {
				dos = new DataOutputStream(client.getOutputStream());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		// 初始化数据
		private String init() {
			try {
				System.out.print("请输入用户名:");
				String uname = console.readLine();
				System.out.print("请输入密码:");
				String upwd = console.readLine();
				return "uname=" + uname + "&" + "upwd=" + upwd;
			} catch (IOException e) {
				e.printStackTrace();
			}
			return "";
		}

		// 发送数据的方法
		public void send() {
			// msg的值为 "uname="+uname+"&"+"upwd="+upwd
			try {
				dos.writeUTF(msg);
				dos.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}

	}

	// 接收
	static class Receive {
		// 输入
		private DataInputStream dis;
		private Socket client;

		public Receive(Socket client) {
			this.client = client;
			try {
				dis = new DataInputStream(client.getInputStream());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		public void receive() {
			String result;
			try {
				result = dis.readUTF();
				System.out.println(result);
			} catch (IOException e) {
				e.printStackTrace();
			}
			// 3、释放资源
			// dos.close();
		}
	}
}
发布了45 篇原创文章 · 获赞 1 · 访问量 5224

猜你喜欢

转载自blog.csdn.net/weixin_42814000/article/details/104397908