Java-网络编程

本文详细介绍了网络编程的基础概念,包括IP地址、端口、传输协议(UDP与TCP)以及Socket编程。重点阐述了如何通过UDP与TCP进行数据传输,并提供了实例代码演示,帮助读者掌握网络编程的核心技术。

网络编程

第一部分

1、网络编程

|--网络编程的本质就是两个设备之间进行数据的交换;设备主要指的是计算机和计算机之间的通讯;
|--数据通讯的原理:数据传输,那么就涉及到了网络;
|--网络通讯的模型:
|--OSI参考模型
|--TCP/IP参考模型

|--网络通讯要素:

|--IP地址:IP地址值最大是255,127.0.0.1-->本地回环地址,主机名:localhost

|--端口号:数据要发送到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用了数字进行标识;

|--传输协议:也就是通讯规则,按照同一种规则进行通讯;

2、IP地址

InetAddress:用于描述IP地址的对象,表示互联网协议 (IP) 地址。

InetAddress 类一些方法:

|--static InetAddress getLocalHost() 获取本地主机
|--String getHostAddress() 获取主机地址
|--String getHostName() 获取主机名
|--static InetAddress getByName(String host) 获取任意一台主机的地址

3、代码体现

<span style="font-family:Microsoft YaHei;font-size:14px;">import java.net.*;
class IpDemo 
{
	public static void main(String[] args) throws Exception 
	{
//		 String getHostAddress() 
//		获取本地主机
		InetAddress i = InetAddress.getLocalHost();
		InetAddress ia = InetAddress.getByName("www.baidu.com");
//		获取主机地址
		System.out.println("address:"+ia.getHostAddress());
//		获取主机名
		System.out.println("name:"+ia.getHostName());
		System.out.println(i.toString());
	}
}</span>
 

3、端口

端口:就是用数字进行标识的,因此没有必要定义对象

4、传输协议

UDP特点:
|--将数据的源和目的封装成数据包中,面向无连接的;就是你在不在和我没关系,你在就收到,不在这个包就丢了,生活中相当于到邮局去寄东西;
|--没个数据包的大小限制在64k之内,可以分成多个包进行发送;
|--因为是无连接的,所以是不可靠的协议;
|--不需要建立连接,速度快;

TCP特点:

|--面向连接的;

|--需要通过三次握手来完成连接的;

|--在连接中可以进行大数据传输;

|--必须建立连接,效率会稍低;

5、Socket

|--Socket就是为网络服务提供的一个机制;
|--通信的两端都有Socket;
|--网络通信其实就是Socket间的通信;
|--数据在两个Socket键通过IO传输;
|--想要通讯,必须要先有港口;
|--其实讲的网络编程,其实就是Socket编程;

第二部分

1、UDP传送

UDP的Socket服务:
|--DatagramSocket此类表示用来发送和接收数据报包的套接字。既有发送又有接受
|--void send(DatagramPacket p)   DatagramPacket: 数据报包用来实现无连接包投递服务。

2、需求一

通过UDP传输方式,将一段文字数据发送出去;
思路:
|--建立UDPSocket服务;
|--提供数据,并将数据封装到数据包中;
|--通过Socket服务的发送功能,将数据包发出去;
|--关闭资源;
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.net.*;
//定义发送端
class UdpSend 
{
	public static void main(String[] args) throws Exception
	{
//		创建udp服务,通过DatagramSocket对象
		DatagramSocket ds = new DatagramSocket(8888);
//		变成了字节数组;
		byte[] buf = "udp ge men lai le".getBytes();
//		DatagramPacket(byte[] buf, int length, InetAddress address, int port)
//		包,把数据全部发出去;要指定地址和端口;
		DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.101"),10000);
//		通过Socket服务将已有的数据包发送出去
		ds.send(dp);
//		关闭资源
		ds.close();

	}
}</span>

通过UDP传输方式:定义一个应用程序,用于接受UDP协议传送的处理数据的;

思路:定义一个UDP的接收端

|--定义UDPSocket服务;

|--定义一个数据包,因为要存储接收到的字节数据,因为数据包对象中有更多功能可以提取字节数据中的不同数据信息

|--通过Socket服务的receive方法将收到的数据存入已经定义好的数据包中,

|--通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上,

|--关闭资源;

|--InetAddress getAddress()  获取Ip地址

|--int getPort()  获取端口

接收端代码体现:接收端要指定一个数字端口10000;能接收到发送端的数据;

<span style="font-family:Microsoft YaHei;">class UdpReceive
{
	public static void main(String[] args) throws Exception
	{
//		建立udp的socket服务,因为这个Socket既能接也能发送;
		DatagramSocket ds = new DatagramSocket(10000);
//		定义数据包,用于存储数据
		byte[] buf = new byte[1024];
		
		DatagramPacket dp = new DatagramPacket(buf,buf.length);

//		通过服务的receive方法将收到的数据存入到数据包中
		ds.receive(dp);//receive阻塞式方法;
//		通过数据包的方法获取其中的数据   拿到了ip地址以后,获取到了一个InetAddress的对象,然后在.getHostAddress(),获取字符串
		String ip = dp.getAddress().getHostAddress();
//		将包中的字节数组变成字符串,只将有效的长度进行转换。
		String data = new String(dp.getData(),0,dp.getLength());
	
		int port = dp.getPort();
		System.out.println(ip+"::"+data+"::"+port);
//		关闭资源。
		ds.close();
	}
}</span>

3、运行结果

4、需求二

UDP键盘录入数据 

<span style="font-family:Microsoft YaHei;font-size:14px;">import java.io.*;
import java.net.*;
//只要用到net包就要用到io包
class UdpSend2 
{
	public static void main(String[] args)throws Exception 
	{
		DatagramSocket ds = new DatagramSocket();
//		键盘录入
		BufferedReader bufr = 
			new BufferedReader(new InputStreamReader(System.in));
//		读取数据
		String line =null;
		while((line = bufr.readLine())!=null)
		{
//			判断结束标记
			if("886".equals(line))
				break;
//			不是886就要先变成字节数据
			byte[] buf = line.getBytes();
//			封装成数据包,获取对方的主机地址
			DatagramPacket dp = 
				new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.101"),10001);
//			发送数据包
			ds.send(dp);
		}
		ds.close();
	}
}
//定义接收端
class UdpReceive2
{
	public static void main(String[] args)throws Exception 
	{
		DatagramSocket ds = new DatagramSocket(10001);
		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());
			System.out.println(ip+"::"+data);
		}
	}

}</span><span style="font-size:18px;">
</span>

5、运行结果

发送端发送数据,接收端接收数据,如果发送端886了,那么发送端就结束了,但是接收端一直是开着的;一直在接收数据的;

6、需求三

需求:编写一个聊天程序;
有接收数据的部分,和发送数据的部分
这两个部分需要同时进行
那就要用到多线程技术
一个线程控制收,一个线程控制发
因为收和发动作是不一致的,所以要定义两个run方法
而且这两个方法要封装到不同的类中;

代码实现

<span style="font-family:Microsoft YaHei;font-size:14px;">import java.io.*;
import java.net.*;

class Send implements Runnable
{
	private DatagramSocket ds;
//	在构造的时候就要传一个Socket进来
	public 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("886".equals(line))
					break;
				byte[] buf = line.getBytes();
				DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.101"),10002);
				ds.send(dp);
			}
		}
		catch (Exception e)
		{
			throw new RuntimeException("发送端失败");
		}
	}
}

class Rece implements Runnable
{
//	作用于整个类
	private DatagramSocket ds;
	public Rece(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);
//				先要获取IP地址
				String ip = dp.getAddress().getHostAddress();
//				获取具体数据
				String data = new String(dp.getData(),0,dp.getLength());
				System.out.println(ip+"::"+data);
			}
		}
		catch (Exception e)
		{
			throw new RuntimeException("接收端失败");
		}
	}
}
class ChatDemo 
{
//	监听端口容易发生Socket异常;
	public static void main(String[] args) throws Exception
	{
//		创建Socket服务
		DatagramSocket sendSocket = new DatagramSocket();
//		接收端要指定端口
		DatagramSocket receSocket = new DatagramSocket(10002);
//		创建线程
		new Thread(new Send(sendSocket)).start();
		new Thread(new Rece(receSocket)).start();
	}
}
</span><strong style="font-size:18px;">

</strong>
</pre></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><h2><span style="font-family:Microsoft YaHei; font-size:18px">运行结果</span></h2></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><div><span style="font-family:Microsoft YaHei; font-size:18px"><img src="https://img-blog.youkuaiyun.com/20150611035745868?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamF2YTk4MzI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /></span></div><div><span style="font-family:Microsoft YaHei; font-size:18px"></span></div></blockquote></blockquote><h1><span style="font-family:Microsoft YaHei; font-size:24px"><strong>第三部分</strong></span></h1><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><h2><span style="font-family:Microsoft YaHei; font-size:18px"><strong>1、TCP传输</strong></span></h2></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><div><span style="font-family:Microsoft YaHei; font-size:14px">|--客户端:Socket:此类实现客户端套接字</span></div></blockquote></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><div><span style="font-family:Microsoft YaHei; font-size:14px">|--Socket(InetAddress address, int port) :一初始化就要指定地址恶化端口</span></div></blockquote></blockquote></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><div><span style="font-family:Microsoft YaHei; font-size:14px">|--该对象在建立时,就要去连接指定的主机,因为tcp是面向连接的,所以在建立Socket服务时,就要有服务端存在,并连接成功,形成通路后,在该通道进行数据的传输;</span></div></blockquote></blockquote></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><div><span style="font-family:Microsoft YaHei; font-size:14px">|--服务端:ServerSocket:此类实现服务器套接字。</span></div></blockquote></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><h2><span style="font-family:Microsoft YaHei; font-size:18px">2、客户端</span></h2></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><div><span style="font-family:Microsoft YaHei; font-size:14px">需求:给服务端发送一个文本数据;</span></div></blockquote></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><p><span style="font-family:Microsoft YaHei; font-size:14px">步骤:</span></p></blockquote></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><p><span style="font-family:Microsoft YaHei; font-size:14px">|--创建Socket服务,并指定要连接的主机和端口;</span></p><p><span style="font-family:Microsoft YaHei; font-size:14px">|--为了发送数据,应该获取Socket流中的输出流;</span></p><p><span style="font-family:Microsoft YaHei"><span style="font-size:14px">|--把字符串变成字符数组写出去;</span></span></p></blockquote></blockquote><h2><span style="font-family:Microsoft YaHei; font-size:18px">3、服务端</span></h2></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><p><span style="font-family:Microsoft YaHei; font-size:14px">需求:定义端点接受数据并打印在控制台上</span></p></blockquote></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><p><span style="font-family:Microsoft YaHei; font-size:14px">步骤:|--建立服务端的socket服务。ServerSocket()并监听一个端口;</span></p></blockquote></blockquote></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><p><span style="font-family:Microsoft YaHei; font-size:14px">   |--获取连接过来的客户端对象;通过ServerSocket的accept方法,没有连接就会等,所以这个方法是阻塞式的方法;</span></p><p><span style="font-family:Microsoft YaHei; font-size:14px">   |--客户端如果发过来数据,那么服务端哟呵使用对应的客户端对象,并获取客户端的读取流发过来的数据;并打印在控制台上;</span></p><p><span style="font-family:Microsoft YaHei; font-size:14px">|--关闭服务;(可选操作)</span></p></blockquote></blockquote></blockquote><h2><span style="font-family:Microsoft YaHei; font-size:18px">4、代码实现</span></h2><div><span style="font-family:Microsoft YaHei"></span><pre name="code" class="java"><span style="font-family:Microsoft YaHei;font-size:14px;">import java.io.*;
import java.net.*;
/*
客户端
*/
class TcpClient
{
	public static void main(String[] args) throws Exception
	{
//		Socket(String host, int port) 
		Socket s = new Socket("192.168.1.101",10003);
//		拿到了Socket中的输出流,
		OutputStream out = s.getOutputStream();
//		把字符串变成字符数组写出去;发送到对应的主机上
		out.write("ge men lai le".getBytes());
		s.close();
	}
}

/*
服务端
*/
class TcpServer
{
	public static void main(String[] args) throws Exception
	{
//		ServerSocket(int port)
//		建立服务端socket服务,并监听一个端口
		ServerSocket ss = new ServerSocket(10003);
//		accept是阻塞式的,通过accept方法获取连接过来的客户端对象;
//		服务端没有流对象;
		Socket s = ss.accept();
//		获取IP地址
		String ip = s.getInetAddress().getHostAddress();
//
		System.out.println(ip+"......connected");
//		获取客户端发过来的数据,那么要使用客户端对象的读取流数据;
		InputStream in = s.getInputStream();
//		创建一个缓冲区把数据存起来
		byte[] buf = new byte[1024];
		int len = in.read(buf);
		System.out.println(new String(buf,0,len));

		s.close();//关闭客户端。服务端要关闭对方
		ss.close();
	}
}</span>
 

5、运行结果

6、TCP传输的原理

7、TCP传输二

需求:演示TCP的传输的客户端和服务端的互访,就是客户端给服务端发送数据,服务端收到后,给客户端反馈信息;
客户端
步骤:
|--建立Socket服务,指定要连接主机主机和端口
|--获取Socket流中的输出流,将数据写到该流中,通过网络发送给服务端;
|--获取Socket流中的输入流,将服务端凡客的数据获取到,并打印;
|--关闭客户端资源;

代码体现

<span style="font-family:Microsoft YaHei;">import java.io.*;
import java.net.*;
class TcpClient2 
{
	public static void main(String[] args) throws Exception
	{
		Socket s = new Socket("192.168.1.101",10004);
//		拿到输出流对象
		OutputStream out = s.getOutputStream();
//		写入数据
		out.write("服务端,hi好".getBytes());
//		读服务端反馈的数据
		InputStream in = s.getInputStream();
		byte[] buf = new byte[1024];
		int len = in.read(buf);
		System.out.println(new String(buf,0,len));
		s.close();
	}
}
//服务端
class TcpServer2 
{
	public static void main(String[] args) throws Exception
	{
		ServerSocket ss = new ServerSocket(10004);
//		拿到客户端对象
		Socket s = ss.accept();
//		拿到客户端的IP地址
		String ip = s.getInetAddress().getHostAddress();
		System.out.println(ip+".....connected");
//		读取客户端的数据
		InputStream in = s.getInputStream();
		byte[] buf = new byte[1024];
		int len = in.read(buf);
		System.out.println(new String(buf,0,len));
//		要给客户端反馈信息
		OutputStream out = s.getOutputStream();
		out.write("哥们收到,客户端也好".getBytes());
		s.close();
		ss.close();
	}
}</span>

运行结果

第四部分

我的总结

|--网络通讯要素:
|--IP地址
|--端口
|--传输协议,国际组织定义了通用协议 TCP/IP

|--UDP需要将数据封装成包,是面向无连接的;

|--UDP的速度快,但是容易丢包

|--聊天就是UDP的,如飞秋,QQ和凌波,视频会议等;-->步话机,对讲机

|--TCP传送是可靠的;但是稍微有点慢,-->打电话,下载

|--凡是带着端口和地址的都是用来定义发送数据包的;

|--Socket主要是记住的是流程,第一步做什么,第二步做什么。。。
|--在建立UDP的接收服务的时候,通常会要监听一个端口,其实就是给这个网络应用程序定义一个数字标识;方便于明确哪些数据过来,该应用程序可以处理;
|--在UDP里面是面向无连接的,因此先开启哪个都是无所谓的;
|--在TCP里面,通路只要一建立,Socket流本身就已经存在了,只需要通过里面的方法拿到里面的输入或者输出流就能有这个流对象,通路有了以后就有了流对象了;
|--打电话的时候就是TCP传输,有听筒和话筒,我向我的话筒里面说,你用你的听筒听到了,你用你的话筒说话,我用我的听筒听到了东西;
|--在TCP里面是面向连接的,所以必须要先启动服务端,要先启动;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值