黑马程序员_JAVA_网络编程

本文深入探讨Java网络编程的核心概念,包括OSI与TCP/IP模型,本地主机地址与端口号,UDP与TCP的区别,以及如何通过Socket实现UDP聊天程序。从理论到实践,为读者提供全面的网络编程知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

OSI参考模型               TCP/IP参考模型
应用层                         应用层
表示层
会话层
传输层                         传输层
网络层                         网际层
数据链路层                  主机-网络层
物理层

InetAddress i = InetAdress.getLocalHost()//获取主机地址,需要捕获或抛出未知主机异常
i.toString();
i.getHostAddress();
i.getHostName();
InetAddress i = InetAdress.getByName("122.206.53.115")//()内可以是IP也可以是主机名,获取任意
一台主机,一个主机名可能返回多个IP可以用getAllByName()获取一个网络地址数组

本地回环地址:127.0.0.1主机名:localhost

端口号:
用于标识进程的逻辑地址,不同进程的标识
有效端口:0~65535,其中0~1024是系统使用的保留端口

UDP
将数据,源和目的封装成数据包中,不需要建立连接
每个数据包的大小限制在64K内‘
无连接,不可靠
速度快
TCP
建立连接建立传输通道
连接中进行大数据量传输
通过三次握手完成连接,协议可靠
效率低

Socket
是为网络服务提供的一种机制
通信两端都有Socket
通过Socket进行通信
数据在两个Socket之间通过IO进行传输

UDP发送

//通过DatagramSocket对象创建UDP服务
DatagramSocket ds = new DatagramSocket(45665);
//确定数据并封装成数据包
byte[] buf =  "udp message".getBytes();
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName(122.206.52.111),10000)
//通过socket服务,用send方法将已有数据包发送出去
ds.send(dp);
//关闭资源

UDP接收
//创建UDP socket ,建立端点
DatagramSocket ds = new DatagramSocket(10000);//定义要监听的UDP端口
//定义数据包用于存储数据
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
//通过服务的receive方法将接收到的数据存入数据包中
ds.receive(dp);
//通过数据包的方法获得其中的数据
String ip = dp.getAdress().getHostAdress();
String data = new String(dp.getData(),0,dp.getLength());
int port = dp.getPort();//45665
//关闭资源
ds.close()

UDP聊天程序

class send implements Runnable{
	private DatagramSocket ds;
	send(DatagramSocket ds){
		this.ds = ds;
	}
	public void run(){
		
		try {
			BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
			String line = null;
			while((line=bufr.readLine())!=null){
				if("over".equals(line))
					break;
				byte[] buf = line.getBytes();
				DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.102"),12200);
				ds.send(dp);
			}
			
//			ds.close();
		}catch (Exception e) {
			throw new RuntimeException("发送失败");
		}
		ds.close();
		
		
		
	}
}

class reve implements Runnable{
	private DatagramSocket ds;
	reve(DatagramSocket ds){
		this.ds = ds;
	}
	public void run(){
		try {
			while(true){
				byte[] buf = new byte[1024];
				DatagramPacket dp = new DatagramPacket(buf,buf.length);
				ds.receive(dp);
				String ip = dp.getAddress().getHostAddress();
				String data = new String(dp.getData(),0,dp.getLength()); 
				int port = dp.getPort();
				System.out.println(ip+"--"+data+"--"+port);
			}
			
		} catch (Exception e) {
			throw new RuntimeException("接收失败");
		}
		
	}
}

class InetCon{
	public static void main(String[] args) throws Exception{
		new Thread(new reve(new DatagramSocket(12204))).start();
		new Thread(new send(new DatagramSocket(12203))).start();
	}
}


TCP分客户端和服务端
客户端对应的对象是Socket
服务端对应的对象是Serversocket


客户端:

步骤:
1.创建Socket服务并指定要连接主机的地址和端口
2.获得Socket流中的输出流,将数据写到该流中,通过网络发送给服务端
3.获取Socket流中的输入流,将服务端反馈的数据获取到,并打印到控制台
4.关闭客户端资源

//创建客户端的socket服务,指定目的主机和端口
Socket s = new Socket("192.168.1.1",19993);
为了发送数据,应该获得都socket流的输出流
OutputStream out = s.getOutputStream();
out.write(".....hello".getBytes());
s.close();


服务端:

1.建立服务端的Socket服务,ServerSocket();
并监听一个端口
2.获取连接的客户端对象
通过ServerSocket的accept方法。没有连接就等,这个方法是阻塞式的。
3.客户端发过来数据,那么服务端就要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据,并打印在控制台上。
4.关闭客户端

//建立服务端的Socket服务,并监听一个端口
ServerSocket ss = new ServerSocket(10052);
//通过ServerSocket的accept方法获取连接的客户端对象
Socket s = ss.accept();
//获得客户端发送的数据,要使用客户端对象的读取流来读取数据
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
//关闭客户端
s.close();

TCP服务器小程序
class  InetServer
{
	public static void main(String[] args) throws IOException
	{
		ServerSocket ss = new ServerSocket(10009);
		Socket s = ss.accept();
		
		String ip = s.getInetAddress().getHostAddress();
		System.out.println(ip+" is connected");
		OutputStream out = s.getOutputStream();
		out.write("欢迎+\r\n".getBytes());
		out.flush();
		s.close();
		ss.close();
	}
}


在客户端与服务端的通信交互时,如果用的是字符流的缓冲区,记得写入之后要flush(),
readLine的结束符是"\r\n";
客户端的Socket.close()是将socket流中加-1,使服务端的readLine方法停下,导致循环结束
PrintWriter的用的写入方法是println()


客户端上传文本文件时,客户端的readLine所在循环可以自动结束,服务端不可以,需要加入标记结束循环,标记可以是时间戳,也可以在末尾直接加"-1";
shutdownOutput();可以关客户端的输出流,在流中加入结束标记-1

浏览器作为客户端时,服务端的输出流要在结束时加-1,并且要记得刷新流

URL统一资源定位符
URL url = new URL("");

String getFile()
     获取URL的文件名//带参数
String getHost()
     获取URL的主机名
String getPath()
     获取URL的路径部分
String getPort()
     获取URL的端口号
String getProtocol()
     获取URL的协议名称
String getQuery()
     获取URL的查询部


URLConnection conn = url.openConnection();

InputStream in = coon.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
String s = new String(buf,0,len);

浏览器和服务器在通信的数据包都包含一个数据头
URLConnection用的应用层协议,不含数据包的头部

域名解析
c:\windows\systems\drivers\ext\host
中存放了本机的默认域名映射,可以用来屏蔽网址
域名解析先找本地,再找域名服务器中的地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值