码迷,mamicode.com
首页 > 其他好文 > 详细

黑马程序员 - 网络编程

时间:2015-08-21 19:21:39      阅读:244      评论:0      收藏:0      [点我收藏+]

标签:

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

网络模型:
OSI参考模型 TCP/IP参考模型

1.找到对方IP
2.数据要发送到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识。
为了方便称呼这个数字,叫做端口,逻辑端口。
3.定义通信规则。这个规则称为协议。国际通用协议 TCP/IP
OSI参考模型 TCP/IP参考模型
应用层
表示层 应用层
会话层
传输层 传输层
网络层 网际层
数据链路层 主机至网络层
物理层
IP地址 :网络中设备的标识。不易记忆,可用主机名。
端口:用于标识进程的逻辑地址,不同进程的标识
有效端口 0~65535,其中0~1024系统使用或保留端口。
以下代码简单演示获取IP地址方法

import java.net.*;
import java.io.*;
class  IPDemo
{
    public static void main(String[] args) throws Exception
    {
        InetAddress i = InetAddress.getLocalHost();             //获取本地IP地址
        System.out.println(i.toString());
        InetAddress ia = InetAddress.getByName("www.baidu.com");//获取百度的IP地址
        System.out.println("name:"+ia.getHostName());            //打印百度的主机名
        System.out.println("address:"+ia.getHostAddress());        //打印百度的主机地址
    }
}

UDP:将数据及源和目的封装成数据包中,不需要建立连接
每个数据包大小限制在64k内
因无连接,是不可靠协议
不许建立连接,速度快
TCP:建立连接,形成传输数据的通道
在连接中进行大数据批量传输
通过三次握手完成连接,是可靠协议
必须建立连接,效率会稍低
Socket:Socket就是为网络服务提供的一种机制。
通信的两端都是有Socket。
网络通信其实就是Socket间的通信。
数据在连个Socket间通过IO传输。
需求:通过UDP传输方式,将一段文字数据发送出去
思路:
1.建立UDPSocket服务
2.提供数据,并将数据封装到数据包中。
3.通过socket服务的发送功能,将数据包发出去。
4.关闭资源。

import java.io.*;
import java.net.*;
class UdpSend   //建立UDP的客户端
{
    public static void main(String[] args) throws Exception
    {
        //1.创建udp服务,通过DatagramSocket对象
        DatagramSocket ds = new DatagramSocket ();
        //2.确定数据,并封装成数据包 
        byte[] buf = "udp ge men lai le ".getBytes(); //创建字节数组存储字符串的字节数据
        DatagramPacket dp =                              //将字节数组封装,并设置目的地为192.168.0.100的10000端口
            new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.0.100"),10000); 
        //3.铜鼓Socket服务,将已有的数据包发送出去,通过send方法发送出去
        ds.send(dp);
        //4.关闭资源
        ds.close();
    }
}

需求:定义一个应用程序,用于接收udp数据
1.定义udpsocket服务。
2.定义一个数据包,因为要存储接收到的字节数据。
因为数据包对象中有更多功能可以提取字节数据的不同数据信息。
3.通过socket服务的recevice方法将受到的数据存入到定义好的数据中
4.通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上
5.关闭资源

import java.io.*;
import java.net.*;
class UdpReceive    //建立UDP的服务端
{
    public static void main(String[] args) throws Exception
    {
        //1.创建udp socket,建立端点,设置端口为10000
        DatagramSocket ds = new DatagramSocket (10000);
        //2.确定数据,用于存储数据
        while(true)
        {
            byte[] buf = new byte [1024];    //建立字节数组
            DatagramPacket dp =                //将数据封装入字节数组中
                new DatagramPacket(buf,buf.length); 
        //3.通过recevice方法将疏导的数据存入数据包中
            ds.receive(dp); //这是阻塞式方法,无数据接收时会停止线程
        //4.通过数据包
            String ip = dp.getAddress().getHostAddress(); //获取数据包中的IP地址
            String data = new String(dp.getData(),0,dp.getLength());//将数据变为字符串
            int port = dp.getPort();//获取数据包中的端口
            System.out.println(ip+"::"+data+":"+port);
        }
        //5.关闭资源
        //ds.close();
    }
}

TCP传输
客户端对应Socket
服务端对应SerrverSocket

客户端:通过查阅Socket对象,该对象建立时,就可以去连接指定的主机。
因为Tcp是面向连接的,所以在建立socket服务时,就需要有服务端存在,
并连接成功形成通路后,在该通路中进行数据传输。
步骤:1.建立Socket服务,并指定要连接的主机和端口
2.获取Socket中的输出流,写入数据后,自动发出
3.提取Socket中的输入流,获取数据后,操作数据(如:打印)。
4.关闭客户端
服务端:1.建立服务端的socket服务,即ServerSocket,并监听一个端口。
2.通过accept()获取连接过来的客户端对象。该方法为阻塞式的,没有连接会自动等待。
3.客户端发过来对象,服务端使用对应客户端对象,并获取该客户端对象的输入流获取数据,
获取该客户端对象的输出流,写入数据,自动发送给客户端。
4.关闭服务端。

演示TCP的传输的客户端和服务端的互访。
需求:客户端给服务器端发送数据,服务端收到,给客户端反馈信息。

客户端:
1.建立socket服务,指定要连接的主机和接口。
2获取socket流中的输出流,将数据写入到该流中,通过网络发送给服务端。
3.获取socket流中的输入流,将服务端反馈的数据获取到,并打印
4.关闭客户端
服务端:
1.建立ServerSocket服务,自定要监听的端口
2.从Socket中获取输入流和输出流
3.从输入流中读取客户端传过来的数据并操作
4.将数据写入输出流并传给客户端
5.关闭服务端

import java.io.*;
import java.net.*;
class TcpClient
{
    public static void main(String [] args) throws Exception
    {
        Socket s = new Socket("192.168.0.100",10001);   //建立Socket服务,指定连接的主机和端口
        OutputStream out = s.getOutputStream();            //获取Socket中的输出流
        out.write("服务端,你好".getBytes());            //写入需要输出的数据
        InputStream in = s.getInputStream();            //获取Socket中的输入流
        byte[] buf = new byte[1024];                    //定义字节数组
        int len = in.read(buf);                            //将输入流中的数据写入字节数组
        System.out.println(new String(buf,0,len));        //将字节数组转为字符串并在控制台上打印
        s.close();                                        //关闭资源
    }
}
class TcpServer
{
    public static void main(String [] args) throws Exception
    {
        ServerSocket ss = new ServerSocket(10001);        //建立服务端ServerSocket对象,指定监听端口
        Socket s = ss.accept();                            //从ServerSockeet中获取Socket对象
        String ip = s.getInetAddress().getHostAddress();//获取Socket中的IP地址
        System.out.println(ip+"....connecting");        //显示正在连接的主机
        InputStream in = s.getInputStream();            //从Socket中获取输入流
        byte[] buf = new byte[1024];                    //定义字节数组
        int len = in .read(buf);                        //将输入流中数据存入字节数组,并将数组有效长度传给len
        System.out.println(new String (buf,0,len));        //将字节数组转为字符串并在控制台上打印
        OutputStream out = s.getOutputStream();            //获取Socket中的输出流
        Thread.sleep(10000);                            //为了掩饰效果,令当亲线程睡一段时间
        out.write("已收到,你也好".getBytes());            //在输入流中写入数据的字节数据
        s.close();                                        //关闭资源
        ss.close();
    }
}

需求:建立一个文本转换服务器
客户端给服务端发送文本,服务端会将文本转成大写并返给客户端
客户端可以一直输入,直至客户端输入over,关闭客户端和服务端。
分析:
客户端:既然是操作设备上的数据,那么久可以使用io技术,并按照io的操作规律来思考
源:键盘录入
目的:网络设备,网络输出流
操作文本数据,选择字符流。
步骤:
1.建立服务
2.获取键盘录入
3.将数据发给服务端
4,获取服务端返回的大写数据
5.关闭数据

本例中出现问题
现象:客户端和服务端都在莫名等待
因为客户端和服务端中都有阻塞式方法,这些方法无结束标记,就会一直等待而导致两端都在等待。
出现此种现象,优先查询阻塞式方法。

import java.io.*;
import java.net.*;
class TransClient
{
    public static void main(String[] args) throws Exception
    {
        Socket s = new Socket("192.168.0.100",10005);
        //定义读取键盘的流对象
        BufferedReader bufr =
            new BufferedReader(new InputStreamReader(System.in));
        //定义目的并与Socket对象中的输出流关联
        BufferedWriter bufw =
            new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        //定义获取服务端的返回的数据(字节流转换成字符流)
        BufferedReader bufr1 =
            new BufferedReader(new InputStreamReader(s.getInputStream()));
        String line = null;
        while ((line=bufr.readLine())!=null)//按行读取输入流中的数据
        {
            if (line.equals("over"))        //定义结束标识
                break;
            bufw.write(line);                //在输出流中写入数据
            bufw.newLine();                    //换行
            bufw.flush();                    //刷新缓冲区
            String lines = bufr1.readLine();//在lines中写入服务端返回的数据
            System.out.println("server:"+lines);
        }
        bufr.close();                        //关闭资源
        bufw.close();
        bufr1.close();
        s.close();
    }
}
class TransServer
{
    public static void main(String[] args) throws Exception
    {
        ServerSocket ss = new ServerSocket(10005);    //创建SeverSocket对象并指定监听端口
        Socket s = ss.accept();                        //从ServerSocket中获取Socket对象
        String ip = s.getInetAddress().getHostAddress();//获取IP地址
        System.out.println(ip+"....connecting");    //显示正在连接的主机
        BufferedReader bufr =          //定义源
            new BufferedReader(new InputStreamReader(s.getInputStream()));
        BufferedWriter bufw =          //定义目的
            new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String line = null;
        while ((line=bufr.readLine())!=null)        //按行读取输入流中的数据
        {
            if (line.equals("over"))                //定义结束标识
                break;            
            System.out.println("client:"+line);        //打印当前客户端传输过来的数据
            bufw.write(line.toUpperCase());            //在输出流中写入读取数据的大写形式
            bufw.newLine();                            //换行
            bufw.flush();                            //刷新缓存区
        }
            ss.close();                                //关闭资源
            s.close();
            bufr.close();
    }
}

需求:上传图片
为保证图片质量用TCP
客户端:
1.建立服务端点
2.读取客户端已有图片数据
3.通过Socket输出流将数据发个服务端
4.读取服务端反馈后关闭。

服务端
这个服务端有个局限性,一次只能连接一个客户端
为了让多个客户端并发访问服务端。
那么服务端最好就是将每个客户端封装到一个单独的线程中,这样就可以同时处理多个客户端。
具体实现:
明确每个客户端要在服务端执行的代码,将其存入run方法。

import java.io.*;
import java.net.*;
class PicClicent
{
    public static void main(String[] args) throws Exception
    {
        Socket s= new Socket("192.168.0.100",10006);        //定义Socket对象并指定连接主机和端口
        FileInputStream fi = new FileInputStream ("d:\\1.jpg");    //定义输入流并关联需操作文件
        OutputStream out = s.getOutputStream();                //从Socket中获取输出流
        byte[] byt = new byte[1024];                        //定义字节数组
        int len = 0;    
        while ((len=fi.read(byt))!=-1)                        //通过循环,将输入流数据存入字节数组
        {
            out.write(byt,0,len);                            //并依次写入输出流,传给服务端
        }
        s.shutdownOutput();                                    //关闭Socket中的输出流
        InputStream in = s.getInputStream();                //获取Socket中的输入流
        byte[] bytin = new byte[1024];                        //定义字节数组
        int num = in.read(bytin);                            //读取字节数组的数据
        System.out.println(new String(bytin,0,num));        //转换成字符串后再控制台上打印
        fi.close();                                            //关闭资源
        s.close();    
    }
}
class PicServer
{
    public static void main(String[] args) throws Exception
    {
        ServerSocket ss = new ServerSocket (10006);            //定义ServerSocket对象并监听指定端口
        while (true)                                        //通过循环多次调用
        {
            Socket s = ss.accept();                            //获取ServerSocket中的Socket对象
            new Thread (new PicThread(s)).start();            //开启复制服务线程
        }
        //ss.close();    
    }
}
class PicThread implements Runnable    //定义图片复制操作线程类
{
    private Socket s;
    PicThread (Socket s)    //将Socket对象传给线程类
    {
        this.s = s;
    }
    public void run()        //覆写run方法,定义需多线程操作的代码
    {
        try
        {
            String ip = s.getInetAddress().getHostAddress();    //获取Socket对象的IP地址
            System.out.println(ip+"....connecting");            //显示正在连接的主机
            InputStream in = s.getInputStream();                //获取Socket对象的输入流
            File file = new File(ip+".jpg");                    //定义新文件为按照IP地址命名
            FileOutputStream fo =new FileOutputStream(file);    //定义输出流与文件关联
            byte[] byt = new byte[1024];                        //定义字节数组
            int len = 0;                                    
            while ((len=in.read(byt))!=-1)                        //通过循环将输入流中的数据依次写入文件
            {
                fo.write(byt,0,len);
            }
            OutputStream out =s.getOutputStream();                //获取Socket中的输出流
            out.write("上传成功".getBytes());                    //在输出流中写入文件复制成功的提示信息
            fo.close();                                            //关闭资源
            s.close();
        }
        catch (Exception e)
        {
            throw new RuntimeException(e);
        }
    }
} 

 

黑马程序员 - 网络编程

标签:

原文地址:http://www.cnblogs.com/myblog-cl/p/4748626.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!