Java中的网络编程

1.什么是Socket

在了解网络编程前,我们首先认识一下Socket,那么什么是Socket呢 ,Socket在计算机的世界中扮演者远程建立连接的角色,而Socket内部通过Tcp/Ip协议将数据传至网络。在Java中提供了几个Socket相关的类封装在操作系统提供的接口:SeverSocket类和Socket类。一个Socket就是由IP地址和端口号(范围在0~65535)之间组成,其中小于1024的端口为特权端口。需要管理员权限,大于1024的端口可以由任意用户的应用程序打开,使用Socket进行网络编程时,本质上就是两个进程之间的网络通信。其中一个进程必须充当服务器端,它会主动的监听某个指定的端口,另一个进程必须充当客户端,它必须主动连接服务器的IP地址和指定端口,如果连接成功。服务器和客户端就成功地建立了一个Tcp连接,双方后续就可以随时发送和接受数据。

因此,当Socket连接成功地在服务器端和客户端之间建立后,

对于服务器来说,它的Socket是指定地IP地址和指定地端口号;

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

2.TCP和UDP

TCP:传输控制协议(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。就是一种传输协议,就像HTTP协议一样,HTTP的目的是指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应,而TCP的目的是为了确保数据传输的可靠性,我给你一个数据包,你一定就要收到,收不到的话那么我就会给你重发,直到我超时放弃你了。HTTP是建立在TCP之上的,当你建立起TCP连接之后,在上面传输的数据用的是HTTP协议。

3.UDP:和TCP相比,UDP编程简单的多,因为UDP没有创建连接,数据包也是依次收发一个,所以没有流的概念,在Java中使用UDP编程,仍然需要使用Socket,因为应用程序在使用UDP时必须指定网络接口(IP地址)和端口号。注意:UDP端口和TCP端口虽然都在使用0~65525,但是它们是两套独立的端口,即一个应用程序用TCP占用了端口1234,不影响另一个应用程序用UDP占用端口1234.
接下来,简单的了解TCP和UDP网络编程的实现

TCP

1.首先创建ServerSocket服务器端对象,并设置端口号(大于1024)。

2.调用accept()方法,监听客户端(是否有客户端连接此端口号),该方法的返回值是Socket

3.如果有客户端连接,继续调用getInetAddress()方法,可以得到连接的客户端的IP地址。

4.通过输入流InputStream读取来自客户端上送的图片文件流,并且将该图片文件流通过Outputstream输出流写入本机自定义地址,(bufferedInputStream和bufferedOutputStream自带缓冲区,可进行批量处理,效率高)每次读取到的图片字节使用字节数组存起来,容量与字节数组容量相等时,写入本地,当图片读取完毕后,通过BufferedWriter反馈给客户端。(小常识:流用完之后都需要关闭)具体代码如下:

public class serverSocket {
	public static void main(String[] args) {
		try {
			//ServerSocket:服务器端进行通信的对象
			ServerSocket server = new ServerSocket(8899);
		
		//死循环:不断接受客户端的链接
		while(true) {
			//服务器进入“等待”状态
			//如果有客户端连接时,该方法返回此客户端的IP
			Socket client = server.accept();//监听客户端
			
			InetAddress clientNetAdress = client.getInetAddress();//得到客户端的地址
			System.out.println("客户端"+clientNetAdress.getHostAddress()+"正在连接...");//得到客户端的ip地址
			
			//接受来自客户端上传的图片
			//输入流:读取来自客户端发送的图片文件流
			//输出流:写入本地图片
			
			String imageName = clientNetAdress.getHostAddress().replace("\\.", "-") +".jpg";
			
			try (InputStream in = client.getInputStream();
					BufferedInputStream bis = new BufferedInputStream(in);
					BufferedOutputStream bos = new BufferedOutputStream(
							new FileOutputStream("C:\\Users\\桦哥的惠普\\Documents\\Tencent Files\\171951798\\FileRecv\\Run\\"+imageName))) {
				//每次读取来自客户端的图片文件流
				//写入本地
				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("opload success!!!");
				write.newLine();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

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

		
	}

}

接下来,就需要创建客户端Socket的对象,传入参数1:本机的IP地址,参数2:服务器端的端口号

通过outputStream输出流将读取到的本地文件流,发送至服务器, bufferInputStream读取本地图片,创建字节数组用于接收读取到的字节,并设置大小,读取完毕后,通过输出流发送至服务器

调用shutdownOutput()方法,让输出暂时关闭。 最后使用BufferedReader输入流读取来自服务器的反馈。具体代码实现如下:

public class demo01 {
	public static void main(String[] args) {
		//Scoket:客户端进行同新的组件
		//本地图片读取=>>通过输出流(发送)服务器
		
		//outputStream:输出流:将读取到的本地文件图片文件流,发送至服务器端
		//BUfferInputStream:输出流,读取本地图片
		
		
		try (Socket soc = new Socket("192.168.254.191",8899);
				OutputStream out  = soc.getOutputStream();
				BufferedInputStream bis = new BufferedInputStream(new FileInputStream("C:\\Users\\桦哥的惠普\\Pictures\\Saved Pictures\\20141223031952490.jpg"));
				){
			//Socket:客户端进行通信的组件
			//循环!
			//每次读取1024个字节
			byte[] bs = new byte[1024];
			int len = -1;
			while((len =bis.read(bs) ) != -1) {
				//将读取到的,通过输出流发送至服务器
				out.write(bs);
			}
			//”输出“暂时关闭(Socket没有关闭)
			soc.shutdownOutput();
			
			//读取来自服务器的反馈
			try(
				BufferedReader reader = new BufferedReader(new InputStreamReader(soc.getInputStream()));){
			String reply = reader.readLine();
			System.out.println("服务器反馈:"+ reply);
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	}

UDP

UDP可以建立双向通信,首先创建Scanner对象,确保我们可以通过输出台进行输入!,再创建Socket对象,当然在UDP中使用的是DatagramSocket,然后创建两个DatagramPacket对象,用于发送和接受,在发送方传入两个参数,参数1:字节数组并设设置字节大小,参数2:new InetSocketAddress并传入另一个客户端的IP地址和端口号,接收方传入字节数组并设置容量,以及容量大小。调用DatagramPacket发送方的对象的setData()方法,并传入发送内容的字节数组,再通过send()方法发送给对方,当然在这里可以进行判断,以发送的内容是“Over”为例,如果接收方收到Over,则代表发送方已下线,否则,继续正常聊天,作为发送方,当然是先发送,后接受,调用receive()方法,用于接收,对方发送过来的是字节,所以我们需要使用receivepacket.getData(),receivepacket.getOffset(),receivepacket.getLength(),将它转换成字符串。最后如果对方发送Over,则证明对方已下线。接收方与发送方一致,当然,前者先发送,在接收,后者先接受,在发送。具体代码实现如下:

public class CharA {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		
		//客户端监听6565端口
		try(DatagramSocket socket = new DatagramSocket(6565);) {
			//提前创建两个Packet数据包,分别用于发送和接收
			DatagramPacket sendpacket3= new DatagramPacket(new byte[1024], 1024,new InetSocketAddress("192.168.254.191",3333));//目的地
			DatagramPacket receivepacket = new DatagramPacket(new byte[1024], 1024);
			
			while(true) {
				//发送
				System.out.print("你说:");
				String sendContent = input.nextLine();
				
				
				sendpacket3.setData(sendContent.getBytes());
				socket.send(sendpacket3);
				if(sendContent.equals("over")) {
					System.out.println("你退出聊天......");
					break;
				}
				
				
				//接收
				socket.receive(receivepacket);
				String receiveContent = new String(receivepacket.getData(),receivepacket.getOffset(),receivepacket.getLength());
				if(receiveContent.equals("over")) {
					System.out.println("对方已下线");
					break;
				}
				System.out.println("他说:"+receiveContent);
			}
		
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

 

public class CharY {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		
		//客户端监听6566端口
		try(DatagramSocket socket = new DatagramSocket(3333);) {
			//提前创建两个Packet数据包,分别用于发送和接收
			DatagramPacket sendpacket = new DatagramPacket(new byte[1024], 1024,new InetSocketAddress("192.168.254.191",6565));
			DatagramPacket receivepacket = new DatagramPacket(new byte[1024], 1024);
			
			while(true) {
				//接收
				socket.receive(receivepacket);
				String receiveContent = new String(receivepacket.getData(),receivepacket.getOffset(),receivepacket.getLength());
				if(receiveContent.equals("over")) {
					System.out.println("对方已下线");
					break;
				}
				System.out.println("他说:"+receiveContent);
				
				//发送
				System.out.print("你说:");
				String sendContent = input.nextLine();
				sendpacket.setData(sendContent.getBytes());
				socket.send(sendpacket);
				if(sendContent.equals("over")) {
					System.out.println("你退出聊天......");
					return;
				}
			}
			
			
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

 对话结果如下图所示。

这样一个简单的聊天窗口就做好了。

  • 12
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值