黑马程序员技术交流社区

标题: 【每天一背】8月4号--网络编程 [打印本页]

作者: 赵顺超    时间: 2014-8-4 09:46
标题: 【每天一背】8月4号--网络编程
本帖最后由 赵顺超 于 2014-8-8 18:03 编辑

网络编程:
1、网络编程概述
        (1)网络模型
                OSI参考模型
                TCP/IP参考模型
        (2)网络通讯要素
                IP地址
                端口号
                传输协议
        (3)网络通讯前提:
                **找到对方IP
                **数据要发送到指定端口。为了标示不同的应用程序,所以给这些网络应用程序都用数字进行标示
                  。这个表示就叫端口。
                **定义通信规则。这个规则称为通信协议,国际组织定义了通用协议TCP/IP
        (4)计算机网络:
                是指将地理位置不同的具有独立功能的多台计算机及其外部设备,
                通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,
                实现资源共享和信息传递的计算机系统。
        (5)IP地址:
                IP地址 = 网络号码+主机地址

                AIP地址:第一段号码为网络号码,剩下的三段号码为本地计算机的号码
                BIP地址:前二段号码为网络号码,剩下的二段号码为本地计算机的号码
                CIP地址:前三段号码为网络号码,剩下的一段号码为本地计算机的号码

                特殊地址:
                127.0.0.1 回环地址,可用于测试本机的网络是否有问题. ping 127.0.0.1   
                ipconfig:查看本机IP地址
                xxx.xxx.xxx.0 网络地址
                xxx.xxx.xxx.255 广播地址

                A        1.0.0.1---127.255.255.254        10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址)                                                        (2)127.X.X.X是保留地址,用做循环测试用的。
                B        128.0.0.1---191.255.255.254        172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。
                C        192.0.0.1---223.255.255.254        192.168.X.X是私有地址
                D        224.0.0.1---239.255.255.254         
                E        240.0.0.1---247.255.255.254
        (6)各种网络分类方式
                A:按网络覆盖范围划分
                  局域网(几米至10公里以内)   城域网(10~100公里)   广域网(几百公里到几千公里)   国际互联网
                B:按网络拓扑结构划分
                  总线型网络   星形网络   环型网络   树状网络   混合型网络
                C:按传输介质划分
                  有线网   无线网
                D:按网络使用性质划分
                  公用网   专用网
        (7)虚拟专用网络(Virtual Private Network ,简称VPN)指的是在公用网络上建立专用网络的技术。
                其之所以称为虚拟网,主要是因为整个VPN网络的任意两个节点之间的连接并没有传统专网
                所需的端到端的物理链路,而是架构在公用网络服务商所提供的网络平台,如Internet
                ATM(异步传输模式〉、Frame Relay (帧中继)等之上的逻辑网络,
                用户数据在逻辑链路中传输。它涵盖了跨共享网络或公共网络的封装、
                加密和身份验证链接的专用网络的扩展。VPN主要采用了隧道技术、加解密技术、
                密钥管理技术和使用者与设备身份认证技术。
        (8)网络模型:
                ****OSI模型
                        应用层
                        表示层
                        会话层
                        传输层
                        网络层
                        数据连接层
                        物理层
                ****TCP/IP模型
                        应用层
                        传输层
                        网际层
                        主机至网络层
2TCPUDP
        (1)UDPTCP的区别:
                UDP
                将数据及源和目的封装成数据包中,不需要建立连接
                每个数据报的大小在限制在64k
                因无连接,是不可靠协议
                不需要建立连接,速度快
                TCP
                建立连接,形成传输数据的通道。
                在连接中进行大数据量传输
                通过三次握手完成连接,是可靠协议
                必须建立连接,效率会稍低
                注:三次握手:
                第一次:我问你在么?
                第二次:你回答在。
                第三次:我反馈哦我知道你在。

作者: 赵顺超    时间: 2014-8-4 09:49
3Socket(UDP传输)
        **Socket就是为网络服务提供的一种机制。
        **通信的两端都有Socket
        **网络通信其实就是Socket间的通信。
        **数据在两个Socket间通过IO传输。
        **Socket主要就是记住流程,代码查文档就行
        (1)UDP传输:DatagramSocketDatagramPacket
                **发送端:
                建立DatagramSocket服务;
                提供数据,并将数据封装到字节数组中;
                创建DatagramPacket数据包,并把数据封装到包中,同时指定IP和接收端口
                通过Socket服务,利用send方法将数据包发送出去;
                关闭DatagramSocketDatagramPacket服务。
                **接收端:
                建立DatagramSocket服务,并监听一个端口;
                定义一个字节数组和一个数据包,同时将数组封装进数据包;
                通过DatagramPacketreceive方法,将接收的数据存入定义好的数据包;
                通过DatagramPacke关闭t的方法,获取发送数据包中的信息;
                关闭DatagramSocketDatagramPacket服务。
                DatagramSocketDatagramPacket方法摘要:
                *****DatagramSocket
                构造方法:
                DatagramSocket()
                        构造数据报套接字并将其绑定到本地主机上任何可用的端口。
                DatagramSocket(int port)
                        创建数据报套接字并将其绑定到本地主机上的指定端口。
                DatagramSocket(int port, InetAddress laddr)
                        创建数据报套接字,将其绑定到指定的本地地址。
                方法摘要:
                void close()
                        关闭此数据报套接字。
                InetAddress getInetAddress()
                        返回此套接字连接的地址。
                InetAddress getLocalAddress()
                        获取套接字绑定的本地地址。
                int getPort()
                        返回此套接字的端口。
                void receive(DatagramPacket p)
                        从此套接字接收数据报包。
                void send(DatagramPacket p)
                        从此套接字发送数据报包。
                ****DatagramPacket
                构造方法:
                DatagramPacket(byte[] buf, int length)
                        构造 DatagramPacket,用来接收长度为 length 的数据包。
                DatagramPacket(byte[] buf, int length, InetAddress address, int port)
                        构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
                InetAddress getAddress()
                        返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
                byte[] getData()
                        返回数据缓冲区。
                int getLength()
                        返回将要发送或接收到的数据的长度。
                int getPort()
                        返回某台远程主机的端口号,此数据报将要发往该主机或者是从该主机接收到的。       
                代码示例:
                ****发送端:
                class UDPSend
                {
                        public static void main(String[] args) throws Exception
                        {
                                DatagramSocket ds = new DatagramSocket();
                                byte[] buf = "这是UDP发送端".getBytes();
                                DatagramPacket dp = new DatagramPacket(
                                        buf,buf.length,InetAddress.getByName("192.168.1.253"),10000);
                                ds.send(dp);
                                ds.close();
                        }
                }
                ****接收端
                class UDPRece
                {
                        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);
                                ds.receive(dp);//将发送端发送的数据包接收到接收端的数据包中
                                String ip = dp.getAddress().getHosyAddress();//获取发送端的ip
                                String data = new String(dp.getData(),0,dp.getLength());//获取数据
                                int port = dp.getPort();//获取发送端的端口号
                                sop(ip+":"+data+":"+port);
                                ds.close();
                        }
                }
                需求1UDP键盘录入数据,并发送给接收端
                发送端:
                class UDPSend
                {
                        public static void main(String[] args) throws Exception
                        {
                                DatagramSocket ds = new DatagramSocket();
                                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("192.168.1.253"),10000);
                                        ds.send(dp);
                                }
                                ds.close();
                        }
                               
                }
                接收端:
                class UDPRece
                {
                        public static void main(String[] args) throws Exception
                        {
                                DatagramSocket ds = new DatagramSocket(10000);
                                while(true)
                                {
                                        byte[] buf = new byte[1024];
                                        DatagramPacket dp = new DatagramPacket(buf,buf.length);
                                        ds.receive(dp);//将发送端发送的数据包接收到接收端的数据包中
                                        String ip = dp.getAddress().getHosyAddress();//获取发送端的ip
                                        String data = new String(dp.getData(),0,dp.getLength());//获取数据
                                        int port = dp.getPort();//获取发送端的端口号
                                        sop(ip+":"+data+":"+port);
                                        ds.close();
                                }
                        }
                       
                }

作者: 赵顺超    时间: 2014-8-4 09:50
需求2:编写简单的聊天工具
                思路:
                        使用多线程技术
                发送端:
                class UDPSend implements Runnable
                {
                        private DatagramSocket ds;
                        public UDPSend(){}
                        public UDPSend(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[] buff = line.getBytes();
                                                DatagramPacket dp = new DatagramPacket(
                                                buf,buf.length,InetAddress.getByName("192.168.1.253"),10000);
                                                ds.send(dp);
                                        }
                                }
                                catch(Exception e)
                                {
                                        throw new RuntimeException("发送失败");
                                }
                        }
                }
                接收端:
                class UDPRece implements Runnable
                {
                        private DatagramSocket ds;
                        public UDPSend(){}
                        public UDPSend(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().getHosyAddress();//获取发送端的ip
                                                String data = new String(dp.getData(),0,dp.getLength());//获取数据
                                                int port = dp.getPort();//获取发送端的端口号
                                                sop(ip+":"+data+":"+port);               
                                        }
                                }
                                catch(Exception e)
                                {
                                        throw new RuntimeException("接收失败");
                                }
                        }
                }
                测试类:
                class UDPTest
                {
                        public static void main(String[] args)
                        {
                                DatagramSocket sendSocket = new DatagramSocket();
                                DatagramSocket receSocket = new DatagramSocket(10000);
                                new Thread(new UDPSend(sendSocket)).start();
                                new Thread(new UDPRece(receSocket)).start();
                        }
                }

作者: 赵顺超    时间: 2014-8-4 09:52
(2)TCP传输
                SocketServerSocket
                建立客户端和服务器端
                建立连接后,通过Socket中的IO流进行数据的传输
                关闭socket
                同样,客户端与服务器端是两个独立的应用程序。
                ****Socket
                **构造方法:
                Socket()
                        通过系统默认类型的 SocketImpl 创建未连接套接字
                Socket(InetAddress address, int port)
                        创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
                Socket(String host, int port)
                        创建一个流套接字并将其连接到指定主机上的指定端口号。
                **方法摘要:
                void close()
                        关闭此套接字。
                InetAddress getInetAddress()
                        返回套接字连接的地址。
                InputStream getInputStream()
                        返回此套接字的输入流。
                OutputStream getOutputStream()
                        返回此套接字的输出流。
                int getPort()
                        返回此套接字连接到的远程端口。
                void shutdownInput()
                        此套接字的输入流置于“流的末尾”。
                void shutdownOutput()
                        禁用此套接字的输出流。
                String toString()
                        将此套接字转换为 String
                ****ServerSocket
                **构造方法:
                ServerSocket()
                        创建非绑定服务器套接字。
                ServerSocket(int port)
                        创建绑定到特定端口的服务器套接字。
                方法摘要:
                Socket accept()
                        侦听并接受到此套接字的连接。
                void close()
                        关闭此套接字。
                InetAddress getInetAddress()
                        返回此服务器套接字的本地地址。
                ****TCP传输流程:
                **客户端:
                建立Socket服务,并制定要连接的主机和端口;
                获取Socket流中的输出流OutputStream,将数据写入流中,通过网络发送给服务端;
                获取Socket流中的输出流InputStream,获取服务端的反馈信息;
                关闭资源。
                **服务端:
                建立ServerSocket服务,并监听一个端口;
                通过ServerSocket服务的accept方法,获取Socket服务对象;
                使用客户端对象的读取流获取客户端发送过来的数据;
                通过客户端对象的写入流反馈信息给客户端;
                关闭资源;
                ****代码示例:
                客户端:
                class TCPClient
                {
                        public static void main(String[] args)
                        {
                                Socket s = new Socket("192.168.1.253",10000);
                                OutputStream os = s.getOutputStream();
                                out.write("这是TCP发送的数据".getBytes());
                                s.close();
                        }
                }
                服务端:
                class TCPServer
                {
                        public static void main(String[] args)
                        {
                                ServerSocket ss = new ServerSocket(10000);
                                Socket s = ss.accept();
                                String ip = s.getInetAddress().getHostAddress();
                                sop(ip);
                                InputStream is = s.getInputStream();
                                byte[] buf = new byte[1024];
                                int len = is.read(buf);
                                sop(new String(buf,0,len));
                                s.close();
                                ss.close();
                        }
                }
                TCP需求1:客户端给服务端发送数据,服务端接收到后反馈信息给客户端
                客户端:
                class TCPClient
                {
                        public static void main(String[] args)
                        {
                                Socket s = new Socket("192.168.1.253",10000);
                                OutputStream os = s.getOutputStream();
                                out.write("这是TCP发送的数据".getBytes());
                               
                                InputStream is = s.getInputStream();
                                byte[] buf = new byte[1024];
                                int len = is.read(buf);
                                sop(new String(buf,0,len));
                                s.close();
                        }
                }
                服务端:
                class TCPServer
                {
                        public static void main(String[] args)
                        {
                                ServerSocket ss = new ServerSocket(10000);
                                Socket s = ss.accept();
                                String ip = s.getInetAddress().getHostAddress();
                                sop(ip);
                                InputStream is = s.getInputStream();
                                byte[] buf = new byte[1024];
                                int len = is.read(buf);
                                sop(new String(buf,0,len));
                                OutputStream os = s.getOutputStream();
                                out.write("这是TCP发送的数据".getBytes());
                                s.close();
                                ss.close();
                        }
                }
       

作者: 赵顺超    时间: 2014-8-4 09:54
TCP需求2:建立一个文本转换服务端,客户给服务端发送文本,服务端将数据转换成大写后返回给客户端
                          当客户端输入over时,转换结束
                客户端:
                class TCPClient
                {
                        public static void main(String[] args)
                        {
                                Socket s = new Socket("192.168.1.253",10000);
                                BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
                                BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(
                                                                                s.getOutputStream()));
                                BufferedReader bufIn = new BufferedReader(new InputStreamReader(
                                                                                s.getInputStream()));
                                String line = null;
                                while((line = bufr.readLine())!=null)
                                {
                                        if("over".equals(line))
                                                break;
                                        bufOut.write(line);
                                        bufOut.newLine();
                                        bufOut.flush();
                                        String retVal = bufIn.readLine();
                                        sop("server:"+retVal);
                                }
                                bufr.close();
                                s.close();
                        }
                }
                服务端:
                class TCPServer
                {
                        public static void main(String[] args)
                        {
                                ServerSocket ss = new ServerSocket(10000);
                                Socket s = ss.accept();
                                String ip = s.getInetAddress().getHostAddress();
                                sop(ip);
                               
                                BufferedReader bufIn = new BufferedReader(new InputStreamReader(
                                                                                s.getInputStream()));
                                BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(
                                                                                s.getOutputStream()));
                                while((line = bufIn.readLine())!=null)
                                {
                                        bufOut.write(line.toUpperCase());
                                        bufOut.newLine();
                                        bufOut.flush();
                                }
                                s.close();
                                ss.close();
                        }
                }
                **需求3:拷贝文件
                客户端:
                class TCPClient
                {
                        public static void main(String[] args)
                        {
                                Socket s = new Socket("192.168.1.253",10000);
                                BufferedReader bufr = new BufferedReader(new FileReader("g:\\demo.txt"));
                                PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
                                String line = null;
                                while((line = bufr.readLine())!=null)
                                {
                                        pw.println();
                                }
                                s.shutDownOutput();
                                BufferedReader bufIn = new BufferedReader(new InputStreamReader(
                                                                                s.getInputStream()));
                                String retVal = bufIn.readLine();
                                sop(retVal);
                                bufr.close();
                                s.close();
                        }
                }
                服务端:
                class TCPServer
                {
                        public static void main(String[] args)
                        {
                                ServerSocket ss = new ServerSocket(10000);
                                Socket s = ss.accept();
                                String ip = s.getInetAddress().getHostAddress();
                                sop(ip);
                               
                                BufferedReader bufIn = new BufferedReader(new InputStreamReader(
                                                                                s.getInputStream()));
                                PrintWriter out = new PrintWriter(new FileWriter"copy.txt",true);
                                String line =null;
                                while((line = bufIn.readLine())!=null)
                                {
                                        out.write(line);
                                }
                                PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
                                pw.println("上传成功");
                                out.close();
                                s.close();
                                ss.close();
                        }
                }
                需求4:上传图片
                客户端:
                class TCPClient
                {
                        public static void main(String[] args)
                        {
                                Socket s = new Socket("192.168.1.253",10000);
                                FileInputStream fis = new FileInputStream("g:\\1.bmp");
                                OutputStream out = s.getOutputStream();
                                byte[] buf = new byte[1024];
                                int len = 0;
                                while((len = bufr.read())!=-1)
                                {
                                        out.write(buf,0,len);
                                }
                                s.shutDownOutput();
                                InputStream in = s.getInputStream();
                                byte[] bufIn = new byte[1024];
                                int lenIn = in.read(bufIn);
                                sop(new String(bufIn,0,lenIn);
                                fis.close();
                                s.close();
                        }
                }
                服务端:
                class TCPServer
                {
                        public static void main(String[] args)
                        {
                                ServerSocket ss = new ServerSocket(10000);
                                Socket s = ss.accept();
                                String ip = s.getInetAddress().getHostAddress();
                                sop(ip);
                                FileOutputStream fos = new FileOutputStream("g:\\copy.bmp");
                                InputStream in = s.getInputStream();
                                byte[] bufIn = new byte[1024];
                                int lenIn = 0;
                                while((lenIn=bufIn.read())!=-1)
                                {
                                        fos.write(bufIn,0,lenIn)
                                }
                                OutputStream outIn = s.getOutputStream();
                                outIn.write("上传成功".getBytes());
                                fos.close();
                                s.close();
                                ss.close();
                        }
                }

作者: 赵顺超    时间: 2014-8-4 09:55
需求5:客户端并发登陆
                        客户端通过键盘录入用户名,服务端对这个用户名进行校验
                        如果用户存在,在服务端现实xxx已登录,并在客户端现实欢迎xxx
                        如果用户不存在,在服务端现实xxx正在尝试登陆,并在客户端现实xxx用户不存在
                        最多登陆三次。
                校验端:
                class User implements Runnable
                (
                        private Socket s;
                        public User(){}
                        public User(Socket s)
                        {
                                this.s=s;
                        }
                        public void run()
                        {
                                try
                                {
                                        BufferedReader bufrIn = new BufferedReader(
                                                        new InputStream(s.getInputStream()))
                                        String name = bufrIn.readLine();
                                        if(name==null)
                                        {
                                                sop("用户名为空");
                                                break;
                                        }
                                        BufferedReader bufr = new BufferedReader(
                                                        new FileReader("user.txt"));
                                        PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
                                        String line = null;
                                        boolean flag = false;
                                        while((line = bufr.reanLine())!=null)
                                        {
                                                if(line.equals(name))
                                                {
                                                        flag = true;
                                                        break;
                                                }
                                                if(flag)
                                                {
                                                        sop(name+"已登陆");
                                                        pw.println("欢迎"+name);
                                                        break;
                                                }
                                                else
                                                {
                                                        sop(name+"正尝试登陆");
                                                        pw.println(name+"用户不存在");
                                                }

                                        }
                                        s.close();
                                }
                                catch(Exception e)
                                {
                                        throw new RuntimeException("用户校验失败");
                                }
                        }
                )
                客户端:
                class LoginClient
                {
                        public static void main(String[] args)
                        {
                                Socket s = new Socket("192.168.1.253",10000);
                                BufferedReader bufr = new BufferedReader(
                                                        new InputStreamReader(System.in)));
                                PrintWriter out = new PrintWriter(s.getOutputStream(),true);
                                BufferedReader bufIn = new BufferedReader(
                                                        new InputStreamReader(s.getInputStream()));
                                for(int i=0;i<3;i++)
                                {
                                        String line = bufr.readLine();
                                        if(line == null)
                                        {
                                                sop("用户名不能为空!");
                                                break;
                                        }
                                        out.write(line);
                                        String retVal = bufIn.readLine();
                                        sop(retVal);       
                                }
                                bufr.close();
                                s.close();
                        }
                }
                服务端:
                class LoginServer
                {
                        public static void main(String[] args)
                        {
                                ServerSocket ss = new ServerSocket(10000);
                                while(true)
                                {
                                        Socket s = ss.accept();
                                        new Thread(new User()).start();
                                }
                        }
                }
作者: AEhaojiu    时间: 2014-8-4 10:27
赞一个。。。
作者: 青偆丶易逝〃    时间: 2014-8-4 10:46
好全面。。。
作者: 新航向    时间: 2014-8-4 10:53
好多,都要背啊?
作者: —Jimmy—    时间: 2014-8-4 11:12
我觉得背是没必要吧,理解练习熟练一下就好了!
作者: 641283812    时间: 2014-8-4 11:16
全部能背下来的是牛人。
作者: 思维    时间: 2014-8-4 11:43
代码你能全记住不?我是真心记不住啊,太多了!
作者: 思维    时间: 2014-8-4 11:46
641283812 发表于 2014-8-4 11:16
全部能背下来的是牛人。

网络编程这一章怎么学!毕老师讲的全是代码根本记不住!需要全部默写出来吗?
作者: s_gd    时间: 2014-8-4 11:52
刚看到网络编程
作者: 楚风★憧憬    时间: 2014-8-4 15:46
很厉害啊 写的很详细啊
作者: 钟伟    时间: 2014-8-4 16:08
真是好多啊
作者: lijiang    时间: 2014-8-4 16:33
网络编程会考到吗?

作者: 赵顺超    时间: 2014-8-6 18:21
lijiang 发表于 2014-8-4 16:33
网络编程会考到吗?

可能有吧,UDP、TCP的区别,然后Socket服务什么的
作者: zhuohong_xiao    时间: 2014-8-6 18:58
厉害啊。看来我要好好学习了a。
作者: liqi    时间: 2014-8-6 20:04
复习了一遍
作者: sk0806    时间: 2014-8-6 21:04
这么多,,鸭梨!
作者: sunny~    时间: 2014-8-6 23:31
学习一下子
作者: 반야_바라_밀    时间: 2014-8-6 23:34
自从看了网络编程,我越来越佩服毕老师了,也对黑马更加期待了。。。
作者: Bule丶    时间: 2014-8-6 23:38
其实这个理解了就会了,UDP和TCP差不太多,就是一个是DatagramSocket一个是Socket和SeverSocket,大部分都是在对流进行操作,UDP就是send一下,receive一下,TCP就是正常的流输入到socket流就可以了,端口是自动监听的,感觉还是流多一点
作者: 7418695lp    时间: 2014-8-7 22:30
网络编程不会考到吧,,背的太全了。。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2