网络编程

网络编程


网络模型


OSI 参考模型

OSI模型
应用层
表示层
会话层
传输层
网络层
数据联络层
物理层

TCP/IP 参考模型

TCP/IP模型
应用层
传输层
网络层
主机至网络层

网络编程三要素

IP地址

1、网络设备中的标识
2、不易记,可用主机名
3、本地回环地址:127.0.0.1 主机名:localhost

端口号

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

传输协议

通讯规则
常见协议 TCP , UDP
UDP 和TCP
UDP:
将数据及源和目的封装成数据包不需要建立连接
每个数据包的大小限制在64k以内
因为无连接,是不可靠的
不需要建立连接,速度快
TCP:
建立连接形成传输数据的通道
在连接中进行大数据传输
通过三次握手建立连接,是可靠的协议
必须要建立连接,效率会稍低
Socket
Soket 就是为网络服务的一种机制。
通信的两端都要socket
网络通信其实就是Socket 间的通信
数据在俩个Socket间通过IO传输

UDP Socket传输协议

UDP文本传输

import java.net.*;
import java.io.*;
/*
 需求:通过udp传输方式,将一段文字数据发送出去。
   定义一个发送窗口
思路:
1、建立udpsocket服务。
2、提供数据,并将数据封装到数据包中,
3、通过socket服务的发送功能,将数据包发送出去。
4、关闭资源
*/
public class Udpsend {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
        //1、创建udp服务,通过DatagramSocket对象。
		DatagramSocket ds= new DatagramSocket();
		
		//2、确定数据,并封装成数据包;DatagramPacket(byte[] buf,int length,InetAddress adress, int port)
		//byte[] buf="udp ge men lai le".getBytes();//静态录入
		//键盘录入
		BufferedReader bufr= new  BufferedReader(new InputStreamReader(System.in));
		String line = null;
		//DatagramPacket dp = new  DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10008);
	    while ((line=bufr.readLine())!=null)
	    {
	    	if("886".equals(line))break;
	    	byte [] buf = line.getBytes();
	    	DatagramPacket dp= new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10008);
	    	//3、通过socket服务,将已有的数据包发送出去,通过send方法
			ds.send(dp);
	    }
	   		
		//4、关闭资源。
		ds.close();
	}

}
/*需求:
 定义一个应用程序,用于接收udp协议传输的数据并处理
 定义udp的接收端
 思路:
 1、定义udpsocket服务。通常会监听一个端口,其实就是给这个接收网路应用的程序定义数字标识。
   方便于明确哪些数据过来应该应用程序可以处理。
 2、定义一个数据包,因为要存储接收到的字节数据。
 因为数据包对象中有更多功能可以提取字节数据中的不同的数据信息。
 3、通过socket服务的receive方法将收到的数据存入已经定义好的数据包中。
 4、通过数据包对象的特有功能,将这些不同的数据取出。打印在控制台上。
 */
class Udpreceive{
	
	public static void main(String[] args) throws Exception{
		//1、创建udp socket,建立端点。
		DatagramSocket ds= new DatagramSocket(10008);
		//循环接收数据
		while(true){
		//2、定义数据包,用于存储数据。
		byte[] buf = new  byte[1024];
		DatagramPacket dp = new DatagramPacket(buf,buf.length);
		//3、通过服务的receive方法将收到的数据存入数据包中。
		ds.receive(dp);
		//4、通过数据包的方法获取其中的数据。
		String ip=dp.getAddress().getHostAddress();
		String data= new String(dp.getData(),0,dp.getLength());
		 int port = dp.getPort();
		 System.out.println(ip+":"+data+":"+port);
		}
		 //5 关闭资源
		 //ds.close();
	}
}


UDP 聊天程序实例

import java.net.*;
import java.io.*;
/*
 需求:编写一个聊天程序。
 有收数据的部分和发数据的部分。
 这俩个部分需要同时执行
 那就需要用到多线程技术。
 一个线程控制收, 一个线程控制发。
 
 因为收和发动作是不一致的,所以要定义俩个run方法。
 而且这俩个方法要封装到不同的类中。
 
  */
public class ChatDemo {

	/**
	 * @param args
	 * @throws SocketException 
	 */
	public static void main(String[] args) throws SocketException {
		// TODO Auto-generated method stub
          DatagramSocket sendSocket = new DatagramSocket();
          DatagramSocket receiveSocket = new DatagramSocket(10008);
          new Thread(new Send(sendSocket)).start();
          new Thread(new Receive(receiveSocket)).start();
          
	}

}
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();
    		DatagramPacket dp= new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),10008);
    		ds.send(dp);
    	}
    	
    	}catch(Exception e){
    	throw new RuntimeException("发送异常");
    	}
    }
}
class Receive implements Runnable{
	private DatagramSocket ds;
    public  Receive(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 date = new String (dp.getData(),0,dp.getLength());
			   System.out.println(ip+":"+date);
		   }
		   }catch(Exception e){
			   throw new RuntimeException("接收失败");
		   }
	   
   } 
}


TCP的Socket传输

1.Socket 和 ServerSocket
2.建立客户端和服务端
3.建立连接收通过Socket对象的IO流进行数据的传输
4,.关闭Socket

TCP 网络书传输 实例

/*
tcp传输。

1.tcp分客户端和服务端。
2.客户端对应的对象是Socket,服务端对应的对象是ServerSocket。
*/
import java.io.*;
import java.net.*;
public class TcpDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
/*
 客户端
 通过查阅socket对象,发现在该对象建立时,就可以去连接指定的主机。
 因为tcp是面向连接的,所以在建立socket服务时,
 就要有服务端存在,并连接成功,形成通路后,在该通道进行数据传输
 
 需求:给服务端发送一个文本数据。
 步骤:
 1.创建Socket服务。并指定要连接的主机和端口。
 */
class TcpClient{
	public static void main(String[] args) throws Exception {
	// TODO Auto-generated method stub
		//创建客户端的socket服务,指定目的主机和端口
		Socket s= new Socket("127.0.0.1",10008);
		//为发送数据,应该获取socket流中的输出流。
		OutputStream out= s.getOutputStream();
		byte[] buf ="tcp ge mem lai le".getBytes();
		out.write(buf);
		
		InputStream in=s.getInputStream();
		byte[] bufin = new byte[1024];
		 int len= in.read(buf);//就收服务端发挥的信息 阻塞式方法。
		 System.out.println(new String (buf,0,len));
		//关闭socket
		s.close();
		
}
}

/*
服务端:
1.建立服务端的socket服务,ServerSocket();
并监听一个端口。
2.获取连接过来的 客户端对象。
通过ServerSocket 的accept方法。没有连接就会等,所以该方法是阻塞方式。
3.客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户对象的读取流来读取数据
并打印在控制台上。
4.关闭服务器。(可选的)
*/
	class TcpServer{
		public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
			//建立服务端的socket服务,并监听一个端口。
		ServerSocket ss= new ServerSocket(10008);
		   // 通过accept方法获取连接过来的客户端对象。
			Socket s = ss.accept();
			//获取客户端发送过来的数据,那么要使用客户端对象的读取流来读数据。
			InputStream in=s.getInputStream();
            byte[] buf=new byte[1024];
			int len=in.read(buf);
			String data=new String(buf,0,len);
			String ip = s.getInetAddress().getHostAddress();
			System.out.println(ip+"------connected!");
			System.out.println(data);
			OutputStream out=s.getOutputStream();
			out.write("哥们收到,你也好!".getBytes());
	}
	}	

TCP传输文本转换功能 实例

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

/*
 需求:建立一个文本转换服务器。
 客户端给服务器发送文本,服务端将文本转化成大写在返回给客户端。
 而且客户端可以不断的进行文本的转换。当客户端输入over时,转换结束。
 
 分析:
 客户端:既然是操作设备的数据,那么久可以使用IO技术,并按照IO的操作规律来思考。
 源:键盘录入。
 目的:网络设备,网络输出流。 而且操作的是文本数据,可以选择字符流。
 
 步骤:
 1.建立服务。
 2.获取键盘录入。
 3.将数据发给服务端。
 4.去服务端返回的大写数据。
 5.结束,关闭资源。
 
 都是文本数据,可以使用字符流进行操作,同时提高效率, 加入缓冲。
  */
public class TransTextDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}

class TransClient{
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
        Socket s = new Socket("127.0.0.1",10008);
        //定义一个键盘输入流
        BufferedReader bufr = 
        		new BufferedReader(new InputStreamReader(System.in));
       //定义的目的,将数据写入到socket 输出流。发给服务端。
        //BufferedWriter  bufOut =
        		//new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        //使用PrintWriter 要比用BufferedWriter 更方便自动刷新和println方法自动换行
        PrintWriter pwOut= new PrintWriter(s.getOutputStream(),true);
        // 定义一个socket 读取流, 读取服务端返回大写信息。
        BufferedReader bufIn=
        		new BufferedReader(new InputStreamReader(s.getInputStream()));
       
        String line=null;
        while ((line=bufr.readLine())!=null){
        	if("over".equals(line))
        		break;
        	pwOut.println(line);
        	//bufOut.write(line);
        	//bufOut.newLine();//必须加入结束标记,证明此行读取结束,防止接收端无限等待。
        	//bufOut.flush();//必须刷新缓冲区,否则数据发不出去。
        	
        	String str =bufIn.readLine();
        	System.out.println(str);
        	
        }
        bufr.close();
        s.close(); 
	}
}
class TransServer{
	public static void main(String[] args) throws Exception{
		ServerSocket ss = new ServerSocket(10008);
		Socket   s = ss.accept();
		String ip=s.getInetAddress().getHostAddress();
		System.out.println(ip+"......connected");
		// 读取socket 读取流中的数据。
		BufferedReader bufIn=
				new BufferedReader(new InputStreamReader(s.getInputStream()));
		//目的。socket输出流。将大写数据写入到socket输出流,并发送个客户端。
		//BufferedWriter bufOut =
				//new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
		PrintWriter pwOut = new PrintWriter(s.getOutputStream(),true);
		String line = null;
		while((line=bufIn.readLine())!=null){

			 pwOut.println(line.toUpperCase());
			//bufOut.write(line.toUpperCase());
			//bufOut.newLine();
			//bufOut.flush();
			
		}
		s.close();
		ss.close();
	}
}

TCP 文件上传 实例

import java.io.*;
import java.net.*;
/*
 需求分析:将一文件通过客户端网路传输到服务器,服务器将其保存
 
 */
public class UploadFile {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
/*
 客户端:通过socket的io流将文件传输到服务端
 */
    class ClientFile{
    	
    	public static void main(String[] args) throws  Exception{
    		// TODO Auto-generated method stub
                Socket  s= new Socket("127.0.0.1",10008);
                //建立一要上传的文件
                File uploadfile= new File("C:/ChatDemo.java");
                //建立socket字符输出流
                PrintWriter  pwOut = new PrintWriter(s.getOutputStream(),true);
                //建立socket输入流
                BufferedReader bufIn =new BufferedReader(new InputStreamReader(s.getInputStream()));
                //判断文件是否存在 存在就进行传输数据
                if(uploadfile.exists()){
                	// 建立文件输入流 读取对应的文件数据
                    BufferedReader bufr= new BufferedReader(new FileReader(uploadfile));
                    //将文件名传输给服务端
                	pwOut.println(uploadfile.getName());
                	//接收服务器传回来的 文件是否存在的信息
                	System.out.print(bufIn.readLine());
                	String line= null;
                	//将接收的文件数据通过socket输出流传输给服务端
                	while((line=bufr.readLine())!=null){
                	pwOut.println(line);
                	}
                	bufr.close();
                	//数据传输完必须告诉服务端输出流传输结束。否则服务端进入无限等待状态。
                	s.shutdownOutput();
                	
                }else{
                	System.out.println("文件不存在!");
                }
                //读取服务端最后的反馈信息
                String str= bufIn.readLine();        
                System.out.println(str);
                
                s.close();
    	}
    }
       
    class ServerFile{
    	public static void main(String[] args)throws Exception {
    		// TODO Auto-generated method stub
            ServerSocket ss= new ServerSocket(10008);
            Socket  s= ss.accept();
            //查询客服端是否连接进来
            String ip=s.getInetAddress().getHostAddress();
    		System.out.println(ip+"......connected");
    		//socket输入流
            BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));
            //socket输出流
            PrintWriter pwOut= new PrintWriter(s.getOutputStream(),true);
            //文件输出流
            PrintWriter pw=null;
            //读取客服端传过来的文件名
            String filename= bufIn.readLine();
           //创建文件
            File  uploadPath=new File("d:/"+filename);
            //判断文件是否存在
            if(!uploadPath.exists()){
            // 建立文件输出流
            	pw  = new PrintWriter(uploadPath);
            	//返回给客户端保存的文件名
            	pwOut.println("上传的文件为:"+filename);
            	  String line =null;
                  while ((line=bufIn.readLine())!=null){
                  	pw.println(line);
                  }
                 
                  pw.close();
                  pwOut.println("上传成功!");
            	
            }else{
            	//如果文件名存在了 返回相关信息
            	pwOut.println("上传的文件存在!");
            	pwOut.println("上传失败!");
               
            }
            //将服务端延迟10秒,避免服务端在客户端没有完成数据接收就断开连接
            new Thread().sleep(10000);           
           // s.close();
            //ss.close();
    	}
    }

TCP图片的并发上传 实例

import java.io.*;
import java.net.*;
import java.util.*;

/*需求:上传图片
/* 客户端
 * 1、服务端
 * 2、读取客户端已有图片信息
 * 3、通过socket 输出流将数据发给服务器
 * 4、读取服务端的反馈信息
 * */
public class Uploadpic {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		
	}
	


}
class PicClient {

 public static void main(String[] args) throws Exception{
	 Scanner sc=new Scanner(System.in);
	 System.out.println("请输入一个上传图片路径");
	 String str=sc.nextLine();
	 
	 List<String> filepath =new ArrayList<String>();
	   filepath.add(str);
	 if(filepath.size()!=1){
		 System.out.println("请选择一个图片路径!");
		 return ;
	 }
	 File file = new File(filepath.get(0));
	 if(!(file.exists()&&file.isFile())){
		 System.out.println("文件不存在或不是文件!");
		 return ;
	 }
	 if(!file.getName().endsWith(".jpg")){
		 System.out.println("必须上传一个jpg格式图片!");
		 return;
	 }
	 if(file.length()>1024*1024*5){
		 System.out.println("图片过大,没安好心!");
		 return;
	 }
	 Socket s=new Socket("127.0.0.1",10008);
	 FileInputStream fis = new FileInputStream (file);
	 OutputStream out=s.getOutputStream();
	 byte[] buf = new byte[1024];
	 int len=0;
	 while((len=fis.read(buf))!=-1){
		 
		 out.write(buf, 0,len);
	 }
	 // 告诉服务端数据已经写完
	 s.shutdownOutput();
	 InputStream in = s.getInputStream();
	 byte[] bufin= new byte[1024];
	 int num = in.read(bufin);
	 System.out.println(new String(bufin,0,num));
	 fis.close();
	 s.close();
 }

}
//创建一个图片上传的线程类,实现客户端并发上传文件;
class PicThread implements Runnable{
	private Socket s=null;
	PicThread(Socket s){
		this.s=s;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		String ip=s.getInetAddress().getHostAddress();
		System.out.println(ip+"......connected!");
		int Count=1;
		try {
			File file=new File("d:/"+ip+".jpg");
			while(file.exists()){
				file=new File("D:/"+ip+"("+(Count++)+").jpg");
			}
			 InputStream in = s.getInputStream();
			 
			 FileOutputStream fos = new FileOutputStream(file);
			 byte[] buf = new byte[1024];
			  int len =0;
			  while ((len=in.read(buf))!=-1){
				  fos.write(buf,0,len);
			  }
			  OutputStream out = s.getOutputStream();
			  out.write("上传成功!".getBytes());
			 fos.close();
			 s.close();
		} catch (Exception e) {
			
			throw new RuntimeException("上传失败!");
		}
		
	}
	
}
class PicServer{
	 public static void main(String[] args) throws IOException{
	 ServerSocket ss = new ServerSocket(10008);
	 while(true){
	 Socket s=ss.accept();
	 new Thread(new PicThread(s)).start();
	}
	// ss.close();
	 
}
}

URL对象的使用

url对象常用方法:
import java.net.*;
/*  URL 对象常用方法
 * getFile() 
          获得此 URL 的文件名。 
 String getHost() 
          获得此 URL 的主机名(如果适用)。 
 String getPath() 
          获得此 URL 的路径部分。 
 int getPort() 
          获得此 URL 的端口号。 
 String getProtocol() 
          获得此 URL 的协议名称。 
 String getQuery() 
          获得此 URL 的查询部分。 
 */
public class URLDemo {

	public static void main(String[] args) throws MalformedURLException {
		// TODO Auto-generated method stub
        URL url = new URL("http://localhost:8080/web/demo.html?a=aa%&b=11");
       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());
       //web访问时一般不带端口号,端口号默认为-1,一帮将其设置为80
       int port = url.getPort();
       if(port==-1)
    	  port=80;
	}
  
}

URLConnection 对象访问服务器实例
import java.io.*;
import java.net.*;
public class URLConnectionDemo {

	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		  // 获取的是tomcat服务器下的web项目里的demo.html文件。  必须先启动tomcat服务器
               URL url = new URL("http://127.0.0.1:8080/web/demo.html");
               //使用URL对象建立的是应用层的连接。返回的是去掉HTTP所识别的信息(也就是消息头部的信息),只返回文件内容信息。
             URLConnection conn=  url.openConnection();
             InputStream in=conn.getInputStream();
             byte[] buf=new byte[1024];
             int len= in.read(buf);
             System.out.println(new String(buf,0,len));
             in.close();
               
	}

}

附加知识:域名解析

    当我们访问一个网络地址时:如http://www.sohu.com/  浏览器首先在本地的地址映射文件配置中找是否有相关的 www.sohu.com 这个名称的地址。如果找不到就会在网络的

DNS(域名解析器)中去请求数据信息,如果域名解析器有这个名称的注册就返回这个名称的IP地址给浏览器,然后浏览器就会根据IP地址去访问IP地址的服务器。

   当我们访问http://localhost:8080/这个地址是他也是先访问我们本机的映射配置文件去找  配置文件就在C:\Windows\System32\drivers\etc下的 hosts文件 内容如下:

  # Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host


# localhost name resolution is handled within DNS itself.
# 127.0.0.1       localhost
# ::1             localhost


127.0.0.1       localhost

  红色部分就是locahost的本地地址映射配置。  所以运用这个配置可以将我们的本地地址配置为我们喜欢的本地名称,也可以过滤一些不好恶意的的网站,如:
将 www.huai.com 配置在我们文件localhost的下边 127.0.0.1        www.huai.com  当在弹出这个网站时就会转到本地,不会再显示那个网站内容。

注意:此配置文件为系统文件配置,修改要谨慎哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值