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

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

网络编程

1.什么是网络编程?

网络编程就是编写网络应用程序,例如QQ,迅雷等都是网络应用程序,它们既可以将数据利用网络发到某太主机上,又能从网络上下载资源,这种利用了网络的程序的编写就叫做网络编程。

2.网络编程三要素

ip地址,端口号,传输协议。

看下图:


OSI参考模型是国际化组织将网络划分的层次,处于模块化的考虑,使得网络这个复杂的问题被分成几个简单的问题来解决。

但是这种划分是比较复杂的,TCP/IP参考模式是在OSI的基础上进行了简化,它将网络划分为四层:应用层,传输层,网际层,网络接口。


3.传输协议和Socket

传输协议:
TCP:面向连接,因此可靠,但是速度慢(下载),通过三次握手,在连接中传输数据。
对于TCP,我们可以将其想象成打电话,我们知道打电话,对方必须接了我们才能通话,而对方只要接了,就建立了连接,而且能肯定将信息传送到对方那里,也就是可靠的。但是速度比较慢,因为我们需要等待对方接电话。但是每次发送多少信息是不限制的,因为只要通着电话,我们想说多久就说多久。
UDP:面向无连接,因此不可靠,但是速度快(QQ),每个数据报在64K以内。
对于UDP,我们可以想象成发短信,只要我们有对方的号码,那么不需要对方同意,我们一样可以将信息发过去,当然了,由于不知道对方的确切状态,比如关机等等,我们不能肯定对方一定接收到了信息,也就是不可靠。但是它速度快,因为我们不需要等待对方的确定。但是我们知道,每条短信的字数是有固定的限制的,这就是数据报的大小。

Socket:套接字,也叫做插座。我们知道,网络应用程序的使用,至少需要有两个端点,例如客户端和服务端,它们通过网络互相交换数据等,那么又是什么帮助他们跟网络进行交互的呢?没错,就是Socket,它作为网络中的端点,负责处理网络问题。


4.使用TCP/UDP的具体步骤

UDP:
DatagramSocket:用于以UDP形式发送接收数据的套接字。
DatagramPacket:用于被DatagramSocket发送和接收的数据格式。
发送数据流程:
1.建立UDPSocket服务。
2.封装数据报DatagramPacket。
3.send方法发送数据。
4.关闭资源
接收数据流程:
1.建立UDPSocket服务,需要监听一个端口。
2.定义一个数据报,存储字节数据。之所以存入数据报对象中,是因为它有很多方法可以提取信息。
3.通过receive(阻塞式)方法将数据存入数据报。
4.通过数据报的方法提取信息,并使用这些信息。
5.关闭资源。
/*
UDP方式发送接收数据(键盘输入,over结束发送,类似收音机,一边发,一边收,单工)
发送数据流程:
1.建立UDPSocket服务。
2.封装数据报DatagramPacket。
3.send方法发送数据。
4.关闭资源
接收数据流程:
1.建立UDPSocket服务,需要监听一个端口。
2.定义一个数据报,存储字节数据。之所以存入数据报对象中,是因为它有很多方法可以提取信息。
3.通过receive(阻塞式)方法将数据存入数据报。
4.通过数据报的方法提取信息,并使用这些信息。
5.关闭资源。

为什么发送接收的while(true)没有死循环呢?
	这是因为Scanner.nextLine和Socket的receive方法都是阻塞式的。
*/
import java.net.*;
import java.util.*;
class Send
{
	public static void main(String[] args) throws Exception
	{
		DatagramSocket ds = new DatagramSocket(8888);//该套接字与8888相关联

		byte[] buf=new byte[1024];
		DatagramPacket dp=new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10000);//通过10000发送数据
		Scanner scn=new Scanner(System.in);
		while(true)
		{
			String data=scn.nextLine();
			dp.setData(data.getBytes());
			dp.setLength(data.getBytes().length);
			ds.send(dp);
			if(data.equals("over"))break;
		}

		ds.close();
	}
}
class Receive
{
	public static void main(String[] args) throws Exception
	{
		DatagramSocket ds=new DatagramSocket(10000);
		
		byte[] buf=new byte[1024];
		DatagramPacket dp=new DatagramPacket(buf,buf.length);
		
		while(true)
		{
			ds.receive(dp);
			
			String ip=dp.getAddress().getHostAddress();
			int port=dp.getPort();
			String data=new String(dp.getData(),0,dp.getLength());
			System.out.println(ip+"在端口:"+port+"上发送:"+data);
			if(data.equals("over"))break;
		}
		ds.close();
	}
}<strong>
</strong>
运行图:


TCP:
Socket:建立TCP中的客户端(建立时就要指定服务端主机)。
ServerSocket:建立TCP中的服务端。
使用客户断IO流传输数据。
关闭资源。
客户端:
1.创建Socket对象,指定服务器主机。
2.为了发送数据,获取输出流,向流中写入数据。
(3.如果服务端有返回信息,那就获取输入流,获取数据。)
4.关闭资源(关闭Socket也就自动关闭了与其相连的资源,例如输出流)。
服务端:
1.创建ServerSocket对象。
2.获取连接过来的客户端Socket对象,通过accept方法,该方法为阻塞方法。
3.获取客户端对象的输入流读取数据并操作数据。
(4.可以通过客户端对象的输出流来将信息发回给客户端)
5.关闭客户端。
6.关闭服务端(可选,一般服务端是不会关闭的)。

//测试TCP方式的客户端和服务端
//客户端将信息发送服务端,服务端打印到控制台(并没有返回信息给客户端)
import java.io.*;
import java.net.*;

class TcpClient 
{
	public static void main(String[] args) throws Exception
	{
		Socket s= new Socket("127.0.0.1",10001);
		
		OutputStream os=s.getOutputStream();
		os.write("我爱你中国".getBytes());
		
		s.close();

	}
}
class TcpServer
{
	public static void main(String[] args) throws Exception
	{
		ServerSocket ss=new ServerSocket(10001);
		
		Socket s=ss.accept();
		
		String ip=s.getInetAddress().getHostAddress();

		System.out.println("ip:"+ip+"...is connected!");

		InputStream is=s.getInputStream();

		byte[] buf=new byte[1024];
		
		int len=is.read(buf);

		System.out.println(new String(buf,0,len));
		
		s.close();

		ss.close();
	}
}
运行图:




5.网络编程小练习

文本转换服务:

//需求:服务端收到客户端信息后,会反馈信息给客户端
//文本转换器,客户端发送文本到服务端,服务端返回大写给客户端
import java.io.*;
import java.net.*;
import java.util.*;
class  TcpClient2
{
	public static void main(String[] args) throws Exception
	{
		//指定服务端主机
		Socket s=new Socket("127.0.0.1",10002);
		//读写键盘
		BufferedReader bw = new BufferedReader(new InputStreamReader(System.in));

		//网络输出流
		BufferedWriter bwOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

		//网络读取流
		BufferedReader bwIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

		String line=null;

		while((line=bw.readLine())!=null)
		{
			bwOut.write(line);
			//重点:1.主要带缓冲区的IO对象要刷新,否则数据并没有写入流中,而是存在于缓冲区中
			//		2.文件结束标记,此处我们使用over为双方认可结束标记(1.over等自定义标记,2.时间戳,3.Socket方法)
			//		3.要发送换行符,因为readLine方法是以换行为标记的,如果读取不到换行,那么它会一直阻塞
			bwOut.newLine();
			bwOut.flush();
			if(line.equals("over"))break;
			System.out.println(bwIn.readLine());
		}
		//关闭流资源
		bw.close();
		s.close();
	}
}


class  TcpServer2
{
	public static void main(String[] args) throws Exception
	{
		//创建服务端Socket对象,指定监听端口号
		ServerSocket ss = new ServerSocket(10002);
		
		Socket s = ss.accept();

		//网络输出流
		BufferedWriter bwOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

		//网络读取流
		BufferedReader bwIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

		String line=null;
		while((line=bwIn.readLine())!=null)
		{
			if(line.equals("over"))break;
			bwOut.write(line.toUpperCase());
			bwOut.newLine();
			bwOut.flush();
		}
		
		s.close();
		ss.close();//可选

	}
}
运行图:

上传文件:

/*
从客户端向服务端上传文件
客户端循环上传文件内容,接收一句服务端返回的上传成功的信息
服务端收到客户端信息,写入本地一个文件。

由于要报告上传进度,因此需要文件大一点比较明显
在此我们选择一个.exe的压缩文件作为上传对象
将文件封装成File对象,方便操作
用来测试Tcp上传文件的测试文件
需求:客户端将此文件上传到服务端
服务端收到后将内容写到本地一个文件中
特点:
1.客户端根据上传进度,每上传百分之十打印到控制台一次
2.服务端将文件写入本地时,文件名为原文件名+上传开始的时间毫秒数
	因此上传前客户端先发应该的文件名过去给服务端创建文件。

发现问题:
==============
1.
如果我们向先写入一个文件名(字符串),再写入一堆数据
那么我们不能全部使用一个字节流输出,否则文件名会混在数据当中,无法获取到。
==============
2.
当我们在客户端从图片或者文件中读取数据时使用BufferedInputStream,向网络输出流写数据使用BufferedOutputStream
在服务端从网络读取流中取数据使用BufferedOutputStream,写入新文件中使用BufferedOutputStream
只要使用了包装类,也就是用到了缓冲区,那么都需要进行flush,否则数据会丢失一部分。

*/
import java.net.*;
import java.io.*;

class TcpUploadFileClient
{
	public static void main(String[] args) throws Exception
	{
		Socket s = new Socket("127.0.0.1",10003);

		//将文件封装成对象
		File file = new File("TcpUpload.exe");
		
		//使用.分割需要写作"\\."来转义。
		String[] strs=file.getName().split("\\.");
		String filename=strs[0]+(System.currentTimeMillis()+"")+"."+strs[1];
		//首先我们要将文件名写到服务端
		//问题:如果使用OutputStream写入文件名的话,文件名的字节数组会和数据混杂在一起
		//因此我们使用BufferedWriter
		BufferedWriter bwOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
		bwOut.write(filename);
		bwOut.newLine();
		bwOut.flush();
		
		//文件读取流
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));

		//网络输出流
		BufferedOutputStream bosOut = new BufferedOutputStream(s.getOutputStream());
		
		//网络读取流,作用就是最后读取服务端发回来的上传成功信息
		BufferedReader brIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

		byte[] buf = new byte[1024];//1K
		int sum = (int)(file.length()/1024.0/10.0);//百分之十需要传几次
		for(int count=0,len=bis.read(buf);len!=-1;len=bis.read(buf))
		{
			count++;
			if(count%sum==0)System.out.println("进度:%"+(10*(count/sum)));
			bosOut.write(buf,0,len);
			bosOut.flush();
		}
		s.shutdownOutput();

		String line = brIn.readLine();
		System.out.println(line);

		bis.close();
		s.close();//关闭此流,与其相关的IO流也就关闭了。


	}
}


class TcpUploadFileServer
{
	public static void main(String[] args) throws Exception
	{
		ServerSocket ss = new ServerSocket(10003);

		Socket s = ss.accept();

		
		//首先读取文件名并创建该文件
		//================================================
		//为什么客户端写入26个字节,但是此处却将buf读满了呢???
		//问题:我们向将文件名写入流,26字节,又将其他内容写入流,而在读取时,read不会知道
		//		哪一部分是文件名,而又没遇到文件结束标记,因此它就会读满buf,也就是1024
		//关键在于使用了InputStream来读取数据,我们知道文件名都是字符,因此可以用BufferedReader来读取。
		BufferedReader brIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
		String filename = brIn.readLine();
		File file = new File(filename);
		file.createNewFile();
		//================================================
		
		
		//网络读取流
		BufferedInputStream bisIn = new BufferedInputStream(s.getInputStream());

		//文件输出流,将数据写入文件中
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));

		//网络输出流,用于再最后向客户端发送反馈信息
		BufferedWriter bwOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

		byte[] buf = new byte[1024];
		for(int len=bisIn.read(buf);len!=-1;len=bisIn.read(buf))
		{
			bos.write(buf,0,len);
			bos.flush();
		}
		

		bwOut.write("上传成功!");
		bwOut.newLine();
		bwOut.flush();

		bos.close();
		s.close();
		ss.close();
	}
}
运行图:



文件并发上传:

/*
并发上传(多线程)
可以上传多种数据类型(文件,音频,视频)
客户端会显示上传进度(百分比)
上传结束服务端返回"上传成功"等信息
结束标记使用shutDownOutput方法。
*/

import java.io.*;
import java.net.*;
class TcpMoreUploadFileClient 
{
	public static void main(String[] args) throws Exception
	{
		Socket s = new Socket("127.0.0.1",10004);

		//将文件封装成对象
		File file = new File("TcpMoreUpload.avi");
		
		//使用.分割需要写作"\\."来转义。
		String[] strs=file.getName().split("\\.");
		String filename=strs[0]+(System.currentTimeMillis()+"")+"."+strs[1];
		//首先我们要将文件名写到服务端
		//问题:如果使用OutputStream写入文件名的话,文件名的字节数组会和数据混杂在一起
		//因此我们使用BufferedWriter
		BufferedWriter bwOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
		bwOut.write(filename);
		bwOut.newLine();
		bwOut.flush();
		
		//文件读取流
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));

		//网络输出流
		BufferedOutputStream bosOut = new BufferedOutputStream(s.getOutputStream());
		
		//网络读取流,作用就是最后读取服务端发回来的上传成功信息
		BufferedReader brIn = new BufferedReader(new InputStreamReader(s.getInputStream()));

		byte[] buf = new byte[1024];//1K
		int sum = (int)(file.length()/1024.0/10.0);//百分之十需要传几次
		int xx=0;
		for(int count=0,len=bis.read(buf);len!=-1;len=bis.read(buf))
		{
			count++;
			if(count%sum==0)System.out.println("进度:%"+(10*(count/sum)));
			bosOut.write(buf,0,len);
			bosOut.flush();
			xx+=len;
		}
		//System.out.println(xx);
		s.shutdownOutput();

		String line = brIn.readLine();
		System.out.println(line);

		bis.close();
		s.close();//关闭此流,与其相关的IO流也就关闭了。

	}
}

class Server implements Runnable
{
	private Socket s;
	Server(Socket s)
	{
		this.s=s;
	}
	public void run()
	{
		try
		{
			BufferedReader brIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
			String filename = brIn.readLine();
			File file = new File(filename);
			file.createNewFile();
		
			//修改回InputStream
			BufferedInputStream bisIn = new BufferedInputStream(s.getInputStream());

			//修改回OutputStream
			BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));

			BufferedWriter bwOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

			byte[] buf = new byte[1024];
			int xx=0;
			for(int len=bisIn.read(buf);len!=-1;len=bisIn.read(buf))
			{
				bos.write(buf,0,len);
				bos.flush();
				xx+=len;
			}
			//System.out.println(xx);
			
			bwOut.write("上传成功!");
			bwOut.newLine();
			bwOut.flush();

			bos.close();
			s.close();
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		
	}
}

class TcpMoreUploadFileServer 
{
	public static void main(String[] args) throws Exception
	{
		ServerSocket ss = new ServerSocket(10004);
		{
			while(true)
			{
				Socket s = ss.accept();
				new Thread(new Server(s)).start();
			}
		}
	}
}
运行图:


图形界面的聊天窗口:

/*
图形化界面的聊天窗口
需求:
1.收发在一起,类似QQ
2.一个程序中既有收功能,也有发功能(多线程技术)
*/
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.text.*;

class Receive implements Runnable
{
	private DatagramSocket ds;
	private TextArea receiveTa;
	private Label ipLab;
	Receive(TextArea receiveTa,Label ipLab)
	{
		this.receiveTa=receiveTa;
		this.ipLab=ipLab;
	}
	public void run()
	{
		try
		{
			ds=new DatagramSocket(10000);
			byte[] buf=new byte[1024];
			DatagramPacket dp=new DatagramPacket(buf,1024);
			while(true)
			{
				ds.receive(dp);
				String ip=dp.getAddress().getHostAddress();
				String data=new String(dp.getData(),0,dp.getLength());
				//处理数据,如何将数据显示到Ta中。
				//方法,通过将展示数据的组件传入该类中,得以在该类中操作
				ipLab.setText("对方IP:"+ip);
				receiveTa.append(new SimpleDateFormat().format(new Date())+"\r\n"+data+"\r\n");
				if(data.equals("over"))break;
			}
			ds.close();
			
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
}
class MyWindow
{
	private Frame win;
	private Label ipLab;
	private TextArea receiveTa,sendTa;
	private Button sendBtn;
	MyWindow(){init();}

	private void init()
	{
		win = new Frame("HQ");
		win.setBounds(300,200,500,350);
		win.setLayout(new FlowLayout());

		ipLab = new Label("对方的IP地址显示区域");
		receiveTa = new TextArea();
		receiveTa.setEditable(false);
		sendTa = new TextArea(3,50);
		sendBtn = new Button("发送");

		win.add(ipLab);
		win.add(receiveTa);
		win.add(sendTa);
		win.add(sendBtn);

		myEvent();

		win.setVisible(true);
		//发送并不在一个独立线程中,而在主线程中
		//new Thread(new Send()).start();
		//接收在一个独立线程中,时刻等待着接收
		//同时我们将展示数据的组件传给接收线程对象,方便其操作该组件内容
		new Thread(new Receive(receiveTa,ipLab)).start();
	}
	private void myEvent()
	{
		win.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
			public void windowOpened(WindowEvent e)
			{
				//窗口出现,发送框即获得焦点
				sendTa.requestFocus();
			}
		});

		//发送按钮添加监听器
		sendBtn.addActionListener(new ActionListener(){
			private DatagramSocket ds;
			public void actionPerformed(ActionEvent e)
			{
				if(sendTa.getText().trim().length()>0)
					sendEvent(ds);
			}
		});
		//文本区域添加监听器(回车即发数据)
		sendTa.addKeyListener(new KeyAdapter(){
			private DatagramSocket ds;
			public void keyPressed(KeyEvent e)
			{
				//响应回车键,发送信息,但是依然有回车键的默认行为
				//也就是换行,也就是每发一次信息,都会直接换到下一行,也就是第二行
				if(sendTa.getText().trim().length()>0)
				{
					if(e.getKeyCode()==KeyEvent.VK_ENTER)
					{
						sendEvent(ds);
						e.consume();//取消默认行为,此处也就是换行的行为
					}
				}
				//不能在没内容的情况下敲击回车,敲了也没反应
				if(e.getKeyCode()==KeyEvent.VK_ENTER)
				{
					e.consume();
				}
			}
		});
	}
	private void sendEvent(DatagramSocket ds)
	{
		try
		{
			ds=new DatagramSocket(8888);
			String data = sendTa.getText();
			DatagramPacket dp=new DatagramPacket(data.getBytes(),data.getBytes().length,
				InetAddress.getByName("127.0.0.1"),10000);
			ds.send(dp);
			ds.close();
			sendTa.setText("");
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
		}
	}
}
class ChatTest 
{

	public static void main(String[] args) 
	{
		new MyWindow();
	}
}
运行图:


6.自定义客户端或者服务端

/*
需求:客户端访问服务器
1.
客户端:浏览器
服务端:自定义
2.
客户端:浏览器
服务端:Tomcat
3.
客户端:自定义浏览器
服务端:Tomcat
*/
import java.io.*;
import java.net.*;
class CustomServer 
{
	public static void main(String[] args) throws Exception
	{
		ServerSocket ss = new ServerSocket(11000);

		while(true)
		{
		Socket s = ss.accept();
		System.out.println(s.getInetAddress().getHostAddress());
		PrintWriter out = new PrintWriter(new OutputStreamWriter(s.getOutputStream()),true);

		//使用PrintWriter要注意:不是所有方法都带自动刷新的。例如write就没有,而println就有
		out.println("<a href='www.baidu.com'>我爱你中国</a>");
		s.close();
		System.out.println("断开连接");
		}
		//ss.close();
		
	}
}
运行图:


7.URL和URLConnection

URL,URLConnection
*URL:统一资源定位符,URI范围要比URL要大。
*URLConnection(应用层对象):内部封装了Socket传输层对象),数据先到传输层,拆包,再将数据主体向上传给应用层。该对象通常由URL的openConnection获得
好处:1.得到的是数据主体,不包括协议头信息。2.自动发送那些协议内容,不需要自己手动发送
//测试URL对象的常用方法
import java.net.*;
class URLDemo 
{
	public static void main(String[] args) throws Exception
	{
		URL url = new URL("http://www.baidu.com/Dir/demo.html?name=helong&age=22");
		
		System.out.println("getProtocol:"+url.getProtocol());
		System.out.println("getHost:"+url.getHost());
		System.out.println("getPort:"+url.getPort());
		System.out.println("getPath:"+url.getPath());
		System.out.println("getFile:"+url.getFile());
		System.out.println("getQuery:"+url.getQuery());

		//如果不指定端口号,那么getPort()==-1,通常操作如下
		int port = url.getPort()==-1?80:url.getPort();
		System.out.println("Port:"+port);

	}
}


/*
 getFile() 
          获取此 URL 的文件名。
 String	getHost() 
          获取此 URL 的主机名(如果适用)。
 String	getPath() 
          获取此 URL 的路径部分。
 int	getPort() 
          获取此 URL 的端口号。
 String	getProtocol() 
          获取此 URL 的协议名称。
 String	getQuery() 
          获取此 URL 的查询部分。
*/
运行图:


//测试:使用URLConnection来连接服务端获取数据
import java.io.*;
import java.net.*;
class URLConnectionDemo 
{
	public static void main(String[] args) throws Exception
	{
		URL url = new URL("http://www.baidu.com");

		URLConnection conn = url.openConnection();

		InputStream in = conn.getInputStream();

		byte[] buf=new byte[1024];
		
		in.read(buf);

		System.out.println(new String(buf,0,100));

	}
}
运行图:

由于百度主页返回的数据量太大,而我们又无法解析,因此只打印了前100个字节的数据。

8.域名解析

我们知道,平时我们需要上哪个网站,例如百度,我们不可能去输入百度的ip地址吧,其实输地址当然也是可以的,但是ip地址比较难以记忆,而网站却非常容易记,但是我们发现,在Socket网络通信中,貌似用的都是ip地址啊,那为什么我们输入网址也能正确访问到我们想要访问的网站呢?这就是域名解析的功劳。
域名解析:将一个网址解析成它对应的ip地址。
我们不仅要问了,这个映射关系式存放在哪里呢?使我们本机吗?这句话只能说对一半错一半,对的是,我们确实可以在本机上配置这个映射关系,错的是我们可以想象,互联网上的网站千千万万,如果都配到我们主机上,那么估计也卡死了吧,所以大部分的网站和它们ip的映射关系是存放在一个叫做域名解析服务器(DNS)上的,下面我们看看使用网址访问一个网站的流程:

我们可以看到,当我们输入一个网址后,浏览器首先到本机的hosts文件中查找是否有对应的映射关系,如果找到了,那么就直接返回ip地址,如果没找到,那么就会前往公网的一台DNS上去查找,找到就返回ip地址,如果还是没找到,则浏览器会给出网址错误之类的提示信息。
配置本地映射表:c-windows-system32-drivers-etc-hosts文件
127.0.0.1----localhost
用处:
1.屏蔽网站例如:127.0.0.1----www.xxx.com
2.加快上网速度:12.13.14.15----www.sina.com(假设12.13.14.15就是新浪的ip地址)

9.网络编程心得总结

网络编程这一部分还是相当重要的,因为我们知道,现在的程序很多都具备网络功能,这也是发展的一个趋势,因为网络有它无与伦比的特点,那就是资源共享,因此网络编程也就自然而然的水涨船高啦。

重点是掌握TCP,UDP的传输,以此使用对应的对象来构建端点进行网络通信和资源共享等。还有比较重要的就是URL,URLConnection两个类,尤其是URLConnection对象,它的优点在于它是应用层的对象,我们使用它时,可以忽略那些传输层的协议头等问题,只专注于应用层的问题即可。



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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值