Tcp编程

基于TCP编程,首先我们得知道什么是Socket,在开发网络应用的时候,会遇到Socket这个概念。Socket是一个抽象概念,一个应用程序通过一个Socket来建立一个远程连接,而Socket内部通过TCP/IP协议把数据传输到网络。

一个Socket是由IP地址和端口号(范围0—65535)组成,可以把Socket简单理解为IP地址加端口号。端口号总是由操作系统分配,它是一个0-65535之间的数字,其中,小于1024的端口属于特权端口,需要管理员权限,大于1024的端口可以由任意用户的应用程序打开

使用Socket进行网络编程时,本质上就是两个进程之间的网络通信,其中一个充当服务器端,它会主动监听某个指定端口,另一个进程必须充当客户端,它必须主动连接服务器的IP地址和指定端口,如果连接成功,服务器端和客户端就成功建立了一个TCP连接,双方后续就可以随时发送和接收数据。

对服务器来说,它的Socket是指定的IP地址和指定的端口号。
对客户端来说,它的Socket是它所在的计算机的IP地址和一个由操作系统分配的随机端口号。

服务器端:

要使用Socket,首先要编写服务器端程序,java标准库中提供了serversocket来实现对指定IP和指定端口的监听,代码如下:

try {
    		 //ServerSocket: 服务器端进行通信的对象 
			ServerSocket sever = new ServerSocket(8848);
			//死循环:不断接受客户端的连接
			while(true) {
			//服务器进入"等待"状态
			//如果有客户端的连接返回客户端的Socket	
			Socket client = sever.accept();
			InetAddress clientAddress = client.getInetAddress();
			System.out.println("客户端:" + clientAddress.getHostAddress() + "开始连接");
			
			//接受来自客户端上传到图片
			//输入流:读取来自客户端发送的图片文件流
			//输出流: 写入本地图片
			String imabeName = clientAddress.getHostAddress().replaceAll("\\.", "-")+".jpg";
			try(InputStream  in = client.getInputStream();
					BufferedInputStream bis = new BufferedInputStream(in);
					BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\20220529\\20220713\\" + imabeName));
					){
				//每次读取来自客户端的图片文件流
				//写入本地
				byte[] buff = new byte[1024];
				int len = -1;
				while((len = bis.read(buff)) != -1) {
					bos.write(buff,0,len);
				}
				System.out.println("图片读取完毕哟~");
				//输出提示信息=> 客户端
				try(BufferedWriter write = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()))){
					write.write("上传完毕哟!");
					write.newLine();
				}
			}
		}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	  

使用accept()方法来监听(表示每当有新的端口连接进来后,就返回一个Socket实例,它是用来和刚连接的客户端进行通信的),如果监听成功,我们会使用一个无限循环来处理客户端的连接。在循环里可以一直调用accept()方法来接收客户端的连接。

  while (true) {
      Socket sock = ss.accept();
      System.out.println("connected from " + sock.getRemoteSocketAddress());
  }

客户端:

相比服务器端,客户端就简单多了,创建一个Socket对象,将IP地址和端口号写入。如果连接成功将返回一个Socket实例,用于后续通信

  //Socket:客户端进行通信的组件
    	          //本地图片读取=>通过输出流发送至服务器
    	         //OutputStream:输出流, 
				   try (Socket client = new Socket("192.168.254.168",8848);
						   OutputStream out = client.getOutputStream();
						   BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\20220529\\员工照片.jpg"))) {
					   
					   byte[] buff = new byte[1024];
					   int len = -1;
					   while((len = bis.read(buff)) != -1) {
						   out.write(buff);
					   }
					   //"输出"暂时结束(Socket没有关闭)
					   client.shutdownOutput();
					   //读取来自服务器的反馈
					   try(BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()))){
						   String reply = reader.readLine();
						   System.out.println("服务器的反馈:" + reply);
					   }
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

注意: 当Socket连接创建成功后,无论是服务器还是客户端,都要使用Socket实例进行网络通信。因为TCP是一种基于流的协议,因此,java标准库使用InputStream和OutputStream来封装Socket数据流。

// 用于读取网络数据:
InputStream in = sock.getInputStream();

// 用于写入网络数据:
OutputStream out = sock.getOutputStream();

写入网络时,必须调用flush()方法,如果不调用,客户端和服务器都收不到数据,因为我们是以流的方式写入数据的,并不是一写就发送到网络了。而是先写入内存缓冲区,直到缓冲区满了,才一次发送到网络,这样提高了传输效率,如果缓冲区的数据很少。我们又想强制把这些数据发送到网络,就必须调用flush()强调把缓冲区数据发送过去。

Scanner index = new Scanner(System.in);
    	while(true) {
		try (Socket client = new Socket("192.168.254.158",8824);
			 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
				BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()))) {
			String question = index.nextLine();
			if(question.equals("over")) {
				break;
			}
			writer.write(question);
			writer.flush();
			
			client.shutdownOutput();
			String answer = reader.readLine();
			 System.out.println("【客户端】来自服务器的回答:" + answer);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
  • 28
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值