Java实现TCP/IP网络编程

Socket

Socket是一个抽象概念,一个应用程序通过一个Socket来建立一个远程连接,而Socket内部通过TCP/IP协议把数据传输到网络。

┌───────────┐                                   ┌───────────┐
│Application│                                   │Application│
├───────────┤                                   ├───────────┤
│  Socket   │                                   │  Socket   │
├───────────┤                                   ├───────────┤
│    TCP    │                                   │    TCP    │
├───────────┤      ┌──────┐       ┌──────┐      ├───────────┤
│    IP     │<────>│Router│<─────>│Router│<────>│    IP     │
└───────────┘      └──────┘       └──────┘      └───────────┘

一个Socket就是由IP地址和端口号(范围是0~65535)组成,可以把Socket简单理解为IP地址加端口号。端口号总是由操作系统分配,它是一个0~65535之间的数字,其中,小于1024的端口属于特权端口,需要管理员权限,大于1024的端口可以由任意用户的应用程序打开。
使用Socket进行网络编程时,本质上就是两个进程之间的网络通信。其中一个进程必须充当服务器端,它会主动监听某个指定的端口,另一个进程必须充当客户端,它必须主动连接服务器的IP地址和指定端口,如果连接成功,服务器端和客户端就成功地建立了一个TCP连接,双方后续就可以随时发送和接收数据。
因此,当Socket连接成功地在服务器端和客户端之间建立后:
●对服务器端来说,它的Socket是指定的IP地址和指定的端口号;
●对客户端来说,它的Socket是它所在计算机的IP地址和一个由操作系统分配的随机端口号。
下面通过一个案例来熟悉一下TCP网络通信的基本步骤:

案例:采用TCP/IP网络通信协议,实现客户端发送文件给服务器端,服务器端接受信息并发送反馈信息给客户端,客户端接受到反馈信息并显示在控制台。

客户端:

1.创建客户端的socket对象,指明服务器端的IP地址和端口号

2.通过客户端的socket对象创建输出流对象

3.文件的写出操作

4.socket.shutdownOutput();// 结束文件发送

5.接受来自服务器端的反馈

//客户端
public class Client {
	public static void main(String[] args) {
		try (// 创建客户端的socket对象,指明服务器端的IP地址和端口号
				Socket socket = new Socket(InetAddress.getLocalHost(), 8899);
				// 通过客户端的socket对象创建输出流对象
				OutputStream os = socket.getOutputStream();
				// 文件的写出操作
				FileInputStream fis = new FileInputStream("E:\\picture\\cat.jpg");) {

			byte[] buff = new byte[1024];
			int len = -1;
			while ((len = fis.read(buff)) != -1) {
				os.write(buff, 0, len);
			}
			socket.shutdownOutput();// 结束文件发送
			//接受来自服务器端的反馈
			try (BufferedReader br= new BufferedReader(new InputStreamReader(socket.getInputStream()));){		
				String result = br.readLine();
				System.out.println("【客户端】来自服务器端的回复:" + result);

			} catch (Exception e) {
				e.printStackTrace();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

服务器端:

1.创建服务器端的serverSocket对象,并指明自己的端口号

2.通过serverSocket对象调用accept方法,接受来自客户端的socket对象

3.通过socket对象创建输入流对象

4.文件的写出操作

5.发送反馈信息

//服务器端
public class Server {
	public static void main(String[] args) {
		try (// 创建服务器端的serverSocket对象,并指明自己的端口号
				ServerSocket serverSocket = new ServerSocket(8899)) {
			// 通过serverSocket对象调用accept方法,接受来自客户端的socket对象
			Socket socket = serverSocket.accept();
			String ip = socket.getInetAddress().getHostAddress();// 获取客户端的IP地址
			System.out.println("【服务器】客户端" + ip + "连接成功...");
			String name = ip.replaceAll("\\.", "\\-");
			// 通过socket对象创建输入流对象
			try (InputStream is = socket.getInputStream();
					FileOutputStream fos = new FileOutputStream("E:\\photo\\" + name + ".jpg");
					// 发送反馈信息
					BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
					) {
				// 文件的写出操作
				byte[] buff = new byte[1024];
				int len = -1;
				while ((len = is.read(buff)) != -1) {
					fos.write(buff, 0, len);
				}
				System.out.println("【服务器】成功接受到客户端" + ip + "发送来的文件并保存至本地!");			
				bw.write("文件接收成功并保存至本地!");
			} catch (Exception e) {
				e.printStackTrace();
			}

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

}

在完成了以上案例后,相信大家对TCP网络编程已经有了基本的认识,下面我们一起完成一个模拟客户端输入姓名,服务器发回反馈信息:xxx,本期双色球中奖号码为【xxxxxx】x的案例。

**
 * 客户端发送信息给服务器端并接受来自服务器端的反馈
 * 
 * @Description
 * @author tyq
 * @version
 * @date 2022-7-14 17:27:34
 *
 */
public class Client {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		while (true) {
			System.out.print("请输入玩家姓名:");
			String name = input.nextLine();
			if (name.equals("over")) {
				break;
			}
			try (Socket socket = new Socket("192.168.254.139", 8888);
					BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
					BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));) {
				// 客户端发送信息给服务器端
				bw.write(name);
				bw.flush();
				socket.shutdownOutput();
				// 客户端接受来自服务器端的信息
				String info = br.readLine();
				System.out.println("【客户端】接受来自服务器端的反馈:"+info);
			}

			catch (IOException e) {

				e.printStackTrace();
			}

		}
		System.out.println("游戏结束!");

	}
}

Java实现TCP/IP网络编程_第1张图片

/**
 * 服务器端接受来自客户端发送的信息,并给予相应的反馈
* @Description
* @author tyq
* @version
* @date 2022-7-14 17:39:13
*
 */
public class Server {
	static Set numberSet=new TreeSet<>();
	public static void main(String[] args) {
		try (ServerSocket serverSocket = new ServerSocket(8888)) {
			while(true) {
				Socket socket = serverSocket.accept();
				String ip = socket.getInetAddress().getHostAddress();
				System.out.println("【服务器】客户端"+ip+"开始登录...");
				try(BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
				    BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
				){

					//接受来自客户端发来的信息
					String name = br.readLine();
                    if(name!=null) {
                    	System.out.println("【服务器】客户端"+ip+"发送姓名为【"+name+"】,已生成双色球号码信息请在客户端查看!");
                    	//反馈给客户端相应的信息
    					//1.产生随机下标:[0,list.size()-1]            *[b-a+1]+a
    					while(numberSet.size()!=6) {
    						int randNum=(int)(Math.random()*33+1);
    						numberSet.add(randNum);
    					}
    					//2.获取集合中的信息
    					String listInfo =numberSet.toString()+(int)(Math.random()*16+1);
    					//3.拼接信息
    					String result=name+"购买本期双色球的幸运号码:"+listInfo;
    					//4.反馈信息给客户端
    					bw.write(result);	
    					//5.清空集合
    					numberSet.clear();
                    }else {
                    	String error="【错误提示】未接受到来自客户端"+ip+"发送来的信息,请重新输入...";
                    	bw.write(error);	
                    }
							
				}catch (Exception e) {
					e.printStackTrace();
				}
				
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

Java实现TCP/IP网络编程_第2张图片

 以上是近期学习的一点收获总结,希望对大家有帮助,如果阅读完本文对你有帮助记得留下你的点赞和关注,谢谢!

你可能感兴趣的:(eclipse,java,tcp/ip)