网络编程

一、网络模型

OSI(Open System Interconnection开放系统互连)参考模型

1.物理层——这一层的数据叫比特

2.数据链路层——这一层的数据叫帧(对数据进行MAC地址,即网卡的地址进行封装与解封装)

3.网络层——对数据进行IP地址的封装与解封装,这一层数据叫数据包

4.传输层——这一层数据叫段,定义了一些传输数据的协议和端口号,对从下层传来的数据进行分段和传输

5.会话层——主要在你的系统之间发起会话或者接受会话请求

6.表示层——主要是进行对接收的数据进行解释、加密或解密、压缩与解压缩等。

7.应用层——主要是一些终端的应用。

二、网络通讯要素

1.IP地址

 本地回环地址:127.0.0.1  主机名:localhost

2.端口号

有效端口:0-65535   其中0-1024系统使用或保留端口。

用于标识进程的逻辑地址,不同进程的标识。

3.传输协议

常见协议:TCP、UDP

(1)UDP

不需要建立连接,每个数据报的大小限制在64K内,因为无连接,是不可靠协议,但是速度快。

(2)TCP

需建立连接,可进行大数据量传输,通过三次握手完成连接,是可靠协议,效率低。

 在java中,网络编程的包为java.net包,在INetAddress接口中封装IP地址,有两个子类INet4Address和INet6Address。

例1:

public static void oper() throws UnknownHostException
{
     //获取取本地主机ip地址对象
     InetAddress ip=InetAddress.getLocalHost();
     System.out.println(ip.getHostAddress());
     System.out.println(ip.getHostName());
    //如何获取指定的主机的ip地址对象
    ip=InetAddress.getByName("my_think"); //InetAddress.getByName("192.168.1.100);也可以
}

三、Socket

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

DatagramSocket此类表示用来发送和接收数据报包的套接字。

DatagramPacket此类表示数据报包。

例2:UDP实例

//发送端
public static void main(String[] args)  throws SocketException
{
     /*
      *创建UDP传输的发送端思路:
      *1. 建立udp的socket服务
      *2. 将要发送的数据封装到数据包中
      *3. 通过udp的socket服务将数据包发送出去
      *4. 关闭socket服务
    */
    DatagramSocket ds=new DatagramSocket();
    // String str="UDP传输演示:哥们来了!";
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
String line=null;
while ((line=bufr.readLine())!=null)
{
if ("over".equals(line))
break;
byte[] buf=line.getBytes();
DatagramPacket dp=new Datagrampacket(buf,buf.length,InetAddress.getName("192.168.1.100",10000);
// byte[] buf=str.getBytes(); // DatagramPacket dp=new Datagrampacket(buf,buf.length,InetAddress.getName("192.168.1.100",10000); ds.send(dp);
    ds.close();
}

//接收端
public static void main(String[] args)
{
     /*
      *建立UDP接收端的思路
      *1. 建立udp socket服务
      *2. 创建数据包,用于存储接收到的数据,方便用数据包对象的方法解析这些数据
      *3. 使用socket服务的rece方法将接收到的数据存储到数据包中。
      *4. 通过数据包的方未能解析数据包中的数据
      *5. 关闭资源
     */
     DatagramSocket ds=new DatagramSocket(10000);
while(true)
{
byte[] buf=new byte[1024]; DatagramPacket dp=new DatagramPacket(buf,buf.legnth); ds.receive(dp); //阻塞式的 String ip=dp.getAddress().getHostAddress(); int port=dp.getPort(); String text=new String(dp.getdata(),0,dp.getLength()); }
ds.close();
}

 例3:TCP传输

Socket和ServerSocket ,这一点和UDP不一样,UDP中DatagramSocket即可接收也可发送。

建立客户端和服务器端

建立连接后,通过Socket中的IO流进行数据的传输

最后需要关闭socket

//TCP客户端
public static void TCPClientDemo throws UnKnowHostException,IOException
{
     /*客户端发数据到服务端
      *Tcp传输,客户端建立的过程
      *1. 创建tcp客户端socket服务,使用的是Socket对象,建议该对象一创建就明确目的地,要连接的主机。
      *2. 如果连接建立成功,说明数据传输通道已建立。该通道就是socket流,是底层建立好的。既然是流,说明这里既有输入,又有输出。想要输入或者输出流对象,可以找socket来获取。
     *可以通过getOutputStream()和getInputStream()来获取两个字节流。
     *3. 使用输出流,将数据写出。
     *4. 关闭资源,其实质是断开连接
     */
     Socket socket=new Socket("192.168.1.100",10002);
     OutputStream out=socket.getOutputStream();
     out.write("tcp演示!");
//读取服务端返回的数据
InputStream in=socket.getInputStream();
byte[] buf=new byte[1024];
int len=in.read(buf);
string text=new String(buf,0,len);
system.out.println(text); socket.close(); }
//TCP服务端 public static void main(String[] args) { /* *建立tcp服务端的思路 *1. 创建服务端socket服务,通过ServerSocket对象 *2. 服务端必须对外提供一个端口,否则客户端无法连接 *3. 获取连接过来的客户端对象 *4. 通过客户端获取socket流读取客户端发来的数据,并打印在控制台上 *5. 关闭资源,需要关客户端和服务端 */ ServerSocket ss=ServerSocket(10002); Socket s=ss.accept(); //获取客户端套接字 String ip=s.getInetAddress().getHostAddress(); InputStream in=s.getInputStream(); byte[] buf=new byte[1024]; int len=in.read(buf); String text=new String(buf,0,len); system.out.println(ip+":"+text);
//使用客户端socket对象的输出流给客端返回数据
OutputStream out=s.getOutputStream();
out.write("收到"); s.close(); ss.close(); }

 在上传文件时,为了告诉服务器,客户端写完了。可添加:

socket.shutdownOutput();

 服务器端因为accept阻塞,所以在一个客户处理完成之前,其他客户必须等待。可以用多线程解决:

public static void main(String [] args) throws IOException
{
     ServerSocket ss=new ServerSocket(10006);
     while(true)
     {
           Socket s=ss.accept();
           //以下多线程执行
           new Thread(new UploadTask(s)).start();
     }
}


//创建UploadTaskod类
public class UploadTask implements Runnable
{
    private Socket s;
    public UploadTask(Socket s){
        this.s=s;
    }
    @override
    public void run()
    {
         String ip=s.getInetAddress().getHostAddress();
         System.out.println(ip+"....connected");
         try{
              InputStream in=s.getInputStream();
              File dir=new File("c:\\pic");
              if (!dir.exist()){
                  dir.mkdirs();
              }
               File file=new File(dir,ip+".bmp");
              FileOutputStream fos=new fileOutputStream(file);
               byte[] buf=new byte[1024];
              int len=0;
              while(l(len=in.read(buf))!=-1){
                  fos.write(buf,0,len);
              }
               OutputStream out=s.getOutputStream();
               out.write("上传成功!",getBytes());
               fos.close();
               s.close();
       }
       catch(Exception e)
       {
 
       }
    }
}

例:自定义www服务器

public static void main(String[] args) throws IOException
{
    ServerSocket ss=new ServerSocket(9090);
    socket s=ss.accept(); 
System.out.println(s.getInetAddress().getHostAddress()+"...Connected"); InputStream in=s.getInputStream(); byte[] buf=new byte[1024]; int len=in.read(buf); String text=new String(buf,0,len); System.out.println(text); PrintWriter out=new PrintWriter(s.getOutputStream(),true); out.println("<font color='red' size='7'>欢迎光临</font>"); s.close(); ss.close(); }

 例:模拟浏览器

public class MyBrowser{
    public static void main(String[] args) throws UnknownHostException,IOException
    {
         Socket s=new Socket("192.168.1.100",8080);
         //模拟浏览器,给tomcat发送符合http协议的请求消息
         PrintWriter out=new printWriter(s.getOutputStream(),true);
         out.println("GET /myweb/1.html HTTP/1.1");
         out.println("Accept: */*");
         out.println("Host:192.168.1.100:8080");
         out.println("Connection:close");
         out.printlnl();
         

         InputStream in=s.getInputStream();
         byte[] buf=n ew byte[1024];
         int len=in.read(buf);
         String str=new String(buf,0,len);
         System.out.println(str);
         s.close();

    }

}

例:URL例

public static void main(String[] args) throws NalformedURLException
{
    String str_url="http://192.168.1.100:8080/myhweb/1.html?name=lisi"
    URL url=new URL(str_url);
    System.out.println(url.getProtocal()); 
    System.out.println(urlgetHost());
    System.out.println(url.getPort());
    System.out.println(url.getFile());
    System.out.println(url.getPath());
    System.out.println(url.getQuery());
    //URL的openStream()方法可以打开此地址的Socket流,并返回此连接的输入流,可用以下方法方法模拟浏览器
    InputStream in=url.openStream();
    byte[] buf=new byte[1024];
    int len=in.read(buf);
    String text=new String(buf,0,len);
    System.out.println(text);
    in.close();
    
}

使用URL对象的openConnection()方法可便的获得输入输出流。

URLConnection conn=url.openConnection();
InputStream in=conn.getInputStream(); //此方法非常简捷
byte[] buf=new byte[1024];
int len=in.read(buf);
String text=new String(buf,0,len);
Sytem.out.print(text);

 

posted @ 2017-10-24 08:38  jsddj  阅读(324)  评论(0编辑  收藏  举报