黑马程序员_java 网络编程-2

本文详细对比了TCP和UDP这两种网络传输协议的特点与应用场景。TCP面向连接,可靠且适用于大量数据传输,如下载程序;而UDP面向无连接,速度快但不可靠,适用于实时通信,如视频会议。此外,还介绍了Socket的基本概念及其在网络编程中的作用。

 ------- android培训java培训、期待与您交流! ----------

TCP和UDP的区别


 UDP:
  是面向无连接的,它将数据集源和目的封装成数据包中,不需要建立连接;它的每个数据报(Datagram)的大小限制在64k以内;因为无连接,是不可靠的协议;同样因为不需要建立里连接,所以速度快。
  应用特点:只求速度快,数据丢失对程序影响不大。
  应用程序实例:聊天室工具、视频、网络会议等。
 TCP:
  需要建立连接,形成传输数据的通道;在连接中进行大量数据传输;通过三次握手协议完成连接,是可靠的协议;因为必须建立连接,所以效率会稍低。(TCP不像UDP需要封包,而且每个包不能超过64k,它可以大量的传输数据)。
  应用特点:适合对数据完整性要求高的程序。
  应用程序实例:下载程序。


Socket


   网络编程其实就Socket编程,Socket是为网络服务的一种机制。(Socket,中文意思为插座) 每个应用程序都有一个Socket通信端点,可以把Socket想象为每个应用程序上的码头。
 通信的两端都有Socket,网络通信其实就是Socket间的通信,数据在两个Socket间通过IO传输。
 
UDP传输


 UDP两端是发送端和接受端。
 DatagramSocket:UDP传输专用的程序通信端点,既能发送也能接受。
 DatagramPacket:数据报包,封装了UDP传输的数据报。里边可以设置要发送的目的地IP地址、端口及要发送的数据。
 广播地址:每个网段尾数为255的IP地址,例如192.168.1.255.

UDP练习:聊天程序

/*
编写一个聊天程序有接受数据的部分,和发数据的部分。
这两部分需要同时执行。那就需要用到多线程技术。
一个线程控制收,一个线程控制发。
因为收和发动作是不一致的,所以要定义两个run方法,而且run方法要封装到不同的类中
*/
import java.net.*;
import java.io.*;
class Send implements Runnable{	
	private DatagramSocket ds;
    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();
				//把发送地址,设为广播地址,
				InetAddress i = InetAddress.getByName("192.168.1.255");	
				DatagramPacket dp=new DatagramPacket(buf,0,buf.length,i,10020);	
			ds.send(dp);
			}
			ds.close();
					}
		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);
				String ip = dp.getAddress().getHostAddress();
				String data = new String(dp.getData(),0,dp.getLength());
			System.out.println("ip:"+ip+" data:"+data);
			}
		}
		catch (Exception e)
		{
			throw new 

RuntimeException("接受端失败");
		}
	}
    }
class  ChatDemo{
	public static void main(String[] args)throws Exception	{
		DatagramSocket sendSoket = new DatagramSocket();
		DatagramSocket receSoket = new DatagramSocket(10020);
		new Thread(new Send(sendSoket)).start();
		new Thread(new Rece(receSoket)).start();
			}
		}

 

TCP传输


 TCP的两端对应的是客户端和服务端。
 Socket:TCP传输客户端通信端点。
 SeverSocket:TCP传输服务端通信端点。
 
 因为TCP需要建立连接,所有Socket客户端一建立就要指定服务端的IP和端口。而在服务端建立时,要设置监听的端口。
 TCP连接成功后,在客户端和服务端就会产生网络流。
 客户端Socket提供对网络流进行读写的输入流和输出流对象。
 服务端操作网络流时,先获取客户端Socket对象,然后利用该Socket的字节输入输出流进行读写操作。
 客户端与服务端进行多次交互时,注意阻塞式方法对程序的影响。
 ServerSocket(int port, int backlog),这个构造函数中backlog用于指定客户端的最大连接数。


 TCP传输中的两个问题


  一、客户端与服务端交互时同时阻塞:
   当客户端和服务端中都都有多个阻塞式方法时,如果使用缓冲区读取每行,没有刷新并加入换行符时,会导致客户端与服务端同时处于阻塞等待状态。
  二、定义文件结束标记:
   当上传文件时,客户端把本地文件变成了IO流,并写入网络输出流时,因为去掉了去掉了window加入的结束标记,使得该IO流没有结束标记,导致服务端读取流中数据时,无法结束。这就需要自定义标记。
  自定义标记有三种方法:
   1.定义”over”这样的字符结束标记;
   2.盖时间戳。
   3.使用Socket的shutdownOutput( )和shutdownInput()方法。

示例代码:简单建立TCP客户端和服务端

/*
演示TCP传输。
1.tcp分客户端和服务端。
2.客户端对应的对象是Socket。服务端对应的对象是SeverSocket
*/
/*
客户端:
通过查阅Socket对象,发现在该对象建立时,就可以连接指定的主机。
因为TCP是面向连接的,所以在建立Socket服务时,就要有服务端存在,并连接成功,形成通路后,在该通道进行数据的传输。
需求:给服务段发送一个文本数据。
步骤:
1.创建Socket服务,并指定要连接的主机和端口。
*/
import java.io.*;
import java.net.*;
class TcpClient  {
	public static void main(String[] args) 

throws Exception	{
		//1.创建客户端的Socket服务,指定目的主机和端口
		Socket s = new Socket("192.168.1.13",10003);
		//2.为了发送数据,应该获取Socket流中的输出流。
		OutputStream out =s.getOutputStream();
		//3.获取输出流后写入数据。
		out.write("Tcp ge men lai le".getBytes());
		//socket关闭客户端Socket服务,也就关闭了网络流资源。
		s.close();
	}
}
/*
服务端:
1.建立服务端的Socket服务,通过SeverSocket();并监听一个端口。
2. 获取连接过了的客户端对象。	通过SeverSocket的accept方法。没有就会等,所以这个方法是阻塞式的。
3.客户端如果发过了数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流读取发过了的数据。并打印在控制台上。
4.关闭服务。(可选操作,服务端一般是一直开着的)。
*/
class  TcpServer{
	public static void main(String[] args) throws Exception	{
		//建立服务端的socket服务,并监听一个端口
		ServerSocket ss = new ServerSocket(10003);
		//通过accept方法获取连接过了的客户端对象,这步很关键。这个方法是阻塞式的
		Socket s = ss.accept();
				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();//可选操作
	}
}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值