黑马程序员—网络编程

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------

一、网络通讯要素

1、找到IP

2、找到端口 :数字标识(0-655350-1024为系统使用保留端口

3、定义通信规则,称为协议。国际组织定义了通用协议TCP/IPUDP

二、网络模型

1OSI参考模型(七层):

物理层—数据链路层—网络层—传输层—会话层—表示层——应用层

2、TCP/IP参考模型(四层)

主机至网络层—网际层—传输层—应用层

三、UDP(面向无连接)TCP

1UDP的特点

将数据及源和目标封装到数据包中,不需要建立连接。

没个数据包的大小限定在64K

是不可靠连接

因为不需要连接,所以速度快

2、TCP的特点

建立连接,形成数据传输通道

在连接中进行大量数据传输

通过三次握手完成连接,是可靠协议

因为必须要建立连接,所以速度会比较慢

    3Socket机制

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

  4、通过UDP传输的方法

建立发送端:

(1)建立Socket服务

DatagramSocket ds=new DatagramSocket();

 (2) 提供数据并将数据封装到数据包

byte[] data=” 数据”.getBytes[];

封装:DatagramPacket dp=new DatagramPacket (data,data.length,InetAddress address,port)

 (3) 通过Socket服务的发送功能将数据包发出去

ds.send(dp);

         (4) 关闭资源

ds.close();

          建立接收端

 (1)建立udp Socket服务。

DatagramSocket ds=new DatagramSocket(port)//要记得监听端口

         (2)定义一个数据包,存储接收到的数据。因为可以通过数据包的放啊提取数据 包中的不同信息.

byte[] buf=new byte[1024];

DatagramPacket dp=new DatagramPacket(buf,buf.length)

   3)通过Soket服务的receive方法接收数据,存入定义好的数据包

ds.recieive(dp);

           4)通过数据包的特有方法提取信息

获取数据:new String(dp.getData(),0,dp.getLength())

获取端口:int port=dp.getPort();

  (5)关闭资源

ds.close();

下面就是利用UDP建立的一个简单聊天程序

 

该聊天软件具备两个部分:接收数据部分和发送数据部分。而且这两个部分需要同时执行,所以就需要使用到多线程技术,其中一个线程发送数据,一个线程接收数据。由于接收和发送的动作不一致,所以要定义两个run方法,而且这两个方法要封装到不同类中。

package Number23;




import java.io.*;
import java.net.*;
//发送端
class send implements Runnable
{
	private DatagramSocket ds;
	send(DatagramSocket ds)
	{
		this.ds=ds;
	}
	
		public void run()
		{
			BufferedReader bf=null;
					try{
						bf=new BufferedReader(new InputStreamReader(System.in));//读取键盘录入
						String line=null;
						while((line=bf.readLine())!=null)
						{
							byte[] by=line.getBytes();
							ds=new DatagramSocket();//建立服务
							//封装数据包
							DatagramPacket dp=new DatagramPacket(by,by.length,InetAddress.getByName("110.85.86.190"),10054);
							ds.send(dp);//发送数据包
						
						}
					}
					catch(Exception ex)
					{}
				}
		
	
	
}
//接收端
class rece implements Runnable


{
	DatagramSocket ds;
	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 data= new String(dp.getData(),0,dp.getLength());
				String ip=dp.getAddress().getHostAddress();
				System.out.println(ip+"......"+data);
				
			 }
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			
		}
		
	}
	
}
public class UdpText
{
	public static void main(String[] args) throws SocketException
	{
		DatagramSocket ds=new DatagramSocket();
		DatagramSocket ds1=new DatagramSocket(10054);
		new Thread(new send(ds)).start();//开启发送端线程
		new Thread(new rece(ds1)).start();//开启接收端线程
	}
}

5、TCP

TCP分为客户端和服务端,客户端对应的是Socket服务,服务端对应的是Server服务。

1、客户端

因为TCP是面向连接的。所以在建立Socket服务的时候就要有服务端存在,并且连接成功。所以建立对象的时候要指定对应主机。

(1)创建Socket服务并指定连接的主机

  Socket s=new Socket(“主机”,端口)

(2)为了发送数据,应该获取Socket流中的输出流

     OutputStream out=s.getOutputStream();

(3)发送数据

Out.write();

(4)关闭服务

s.close();

2、服务端

(1)建立服务端的Socket服务

ServerSocket ss=new ServerSocket(监听端口);

(2)连接一个客户端对象。

Socket s=ss.accepet();

(3)要使用客户端发来的数据,应该获取到客户端的读取流

InputStream in=s.getInputStream();

(4)关闭资源(可选)

Ss.close();

当多个客户端并发的访问服务端,那么服务端要将每个客户端封装到单独的线程,这样服务端就可以同时处理多个客户端。

下面就是一个多个客户端往服务端上传文件的例子:

import java.io.*;
import java.net.*;
class Client 
{
	

	public static void main(String[] args) throws UnknownHostException, IOException
	{
		if(args.length!=1)
		{
			System.out.println("请选择一个文件");
			return;
		}
		File file=new File(args[0]);
		if(!(file.isFile()&&file.exists()))
		{
			System.out.println("文件不存在或者不是文件");
			return;
		}
		
		Socket s=new Socket("169.254.68.164",10050);//建立服务
		FileInputStream fs=new FileInputStream(file);//关联一个文件
		OutputStream op=s.getOutputStream();//获取输出流
		byte[] buf=new byte[1024];
		int num=0;
		while((num=fs.read(buf))!=-1)
		{
			op.write(buf,0,num);
			op.flush();
			
		}
		s.shutdownOutput() ;//关闭客户端输出流,相当于给服务端一个结束标记
		InputStream is=s.getInputStream();
		byte[] by=new byte[1024];
		int line=is.read(by);//读取服务端返回的数据
		System.out.println(new String(by,0,line));
		fs.close();
		s.close();
	}
}

class ServerThread implements Runnable
{
	 private Socket s;
	 ServerThread(Socket s)
	 {
		 this.s=s;
	 }
	public void run() 
	 {
	 	try
	 	{
	 		int count=1;
	 		String ip=s.getInetAddress().getHostAddress();
	 		System.out.println(ip);
	 		InputStream is=s.getInputStream();
	 		File file=new File(ip+".jpg");
	 		while(file.exists())
	 			file=new File(ip+"("+(count++)+")"+".jpg");//
	 		
	 			
	 		FileOutputStream fos=new FileOutputStream(file);
	 		byte[] by=new byte[1024];
	 		int num=0;
	 		
	 		while((num=is.read(by))!=-1)
	 		{
	 			fos.write(by,0,num);
	 			fos.flush();
	 		}
	 		OutputStream os=s.getOutputStream();
	 		os.write("上传成功".getBytes());
			fos.close();
			s.close();
	 	}
	 	catch(Exception e)
	 	{
		
		}
	 		
	 }	
	 	
	 
}
class ServerClit
{
	public static void main(String[] args) throws IOException
	{
		ServerSocket ss=new ServerSocket(10050);
		while(true)
		{
			Socket s=ss.accept();
			new Thread(new ServerThread(s)).start();
		}
		
	}
}

4)、练习:客户端并发登录

需求:客户端通过键盘录入用户名,服务端对这个用户名进行校验。

如果该用户存在在服务器上显示xxx,已登录。并在客户端显示xxx,欢迎观临。

如果该用户不存在则在服务器端显示xxx,尝试登录。并在客户端显示xxx,该用户不存在。

最多只能登录三次。

import java.io.*;
import java.net.*;
//客户端

public class LoginClient 
{
	public static void main(String[] args) throws IOException
	{ 
		Socket s=new Socket("169.254.68.164",10051);
		
		BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
		
		PrintWriter out=new PrintWriter(s.getOutputStream(),true);
		BufferedReader brin=new BufferedReader(new InputStreamReader(s.getInputStream()));
		
		for(int x=0;x<3;x++)
		{
				String line=bf.readLine();
				out.println(line);
				String info=brin.readLine();
				
				System.out.println(info);
				if(info.contains("欢迎"))
					break;
		}
		
	}
}

import java.io.*;
import java.net.*;
//服务端
public class LoginServer
{
	public static void main(String[] args) throws IOException
	{
		ServerSocket ss=new ServerSocket(10051);
		while(true)
		{
			Socket s=ss.accept();
			new Thread(new LoginSocketThread(s)).start();
		}
	}
}
class LoginSocketThread implements Runnable
{
	private Socket s;
	LoginSocketThread(Socket s)
	{
		this.s=s;
		
	}
	public void run()
	{
		String ip=s.getInetAddress().getHostAddress();
		System.out.println(ip+"连接成功");
		File file=new File("G:\\login.txt");//模拟一个数据库,存放登入名
		try{
			for(int x=0;x<3;x++)
			{
				BufferedReader bfin=new BufferedReader(new InputStreamReader(s.getInputStream()));
				String name=bfin.readLine();;//读取输入的名字
					if(name==null)
						break;
				BufferedReader br=new BufferedReader(new FileReader(file));//读取流读取文件的登入名
				PrintWriter pwout=new PrintWriter(s.getOutputStream(),true);
				String num=null;
				boolean flag=false;//设置一个判断标记
				while((num=br.readLine())!=null)
				{
					if(num.equals(name))
					{
						flag=true;
						break;
					}
				}
				if(flag)
				{
					System.out.println(name+"登入成功");
					pwout.println("本站欢迎你");
					break;
				}
				else
				{
					System.out.println(name+"尝试登入");
					pwout.println("对不起,用户名不存在");
				}
				
			}
			s.close();
			
			}
		catch(Exception e)
		{
			
		}
	}

}

四:URL类

1、类 URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。

部分URL方法

(1)getProtocol()
          获取此 URL 的协议名称。

(2)getHost()
          获取此 URL 的主机名(如果适用)。

(3)getPort()
          获取此 URL 的端口号。

(4)getFile()
          获取此 URL 的文件名。

(5)getPath()
          获取此 URL 的路径部分

(6)getQuery()
          获取此 URL 的查询部分。

2、URLConnection

抽象类 URLConnection 是所有类的超类,它代表应用程序和 URL 之间的通信链接。此类的实例可用于读取和写入此 URL 引用的资源。通常,创建一个到 URL 的连接需要几个步骤:


1 通过在 URL 上调用 openConnection 方法创建连接对象。

2 处理设置参数和一般请求属性。

3 使用 connect 方法建立到远程对象的实际连接。

4 远程对象变为可用。远程对象的头字段和内容变为可访问

 常用到的方法:

(1)getInputStream()
          返回从此打开的连接读取的输入流。

(2)getURL()
          返回此 URLConnection 的 URL 字段的值。

(3)getOutputStream()
          返回写入到此连接的输出流

 用此类我们模拟一个ie就很简便了,如下:

import java.io.*;

import java.net.*;


public class MyIe
{
	public static void main(String[] args) throws UnknownHostException, IOException
	{
		
		//Socket s=new Socket("192.168.1.1",8080);
		InetAddress i=InetAddress.getLocalHost();
		
		String ip=i.getHostAddress();
		String name=i.getHostName();
		System.out.println(ip+"...."+name);
		URL url=new URL("http://120.37.213.168/myweb/4.java");
		URLConnection uc=url.openConnection();
		InputStream in=uc.getInputStream();
		
		int num=0;
		while((num=in.read())!=-1)
		{
			System.out.print((char)num);
		}
	}
}


总结:

学习完网络编程发现,要学好就得对IO流的操作要很熟悉。里面很多操作都 是跟IO的操作紧密相连 的。不管是UDP还是TCP都有可能要用到一些。所以很有必要去复习下IO的一些操作。


------------------------ ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值