黑马程序员_Java学习日记第八天--TCP/UDP通信、正则表达式

------- android培训、 java培训、期待与您交流! ----------

UDP/TCP

如何实现通信:

1,找到对方IP

2,数据要发送到对方指定的应用程序上。为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识。为了方便称呼这个数字,叫做端口。逻辑端口。

3,定义通信规则。这个通信规则称为协议。

国际组织定义了通用协议。

 

网络模型

    OSI参考模型

    TCP/IP参考模型

网络通讯要素

    IP地址

       网络中设备的标识

       不易记忆,可用主机名

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

    端口号

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

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

    传输协议

       通讯的规则

       常见协议:TCP,UDP

   

OSI参考模型   TCP/IP参考模型

应用层

应用层

表示层

会话层

传输层

传输层

网络层

网络层

数据链路层

主机至网络层

物理层

 

UDP

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

    每个数据包的大小限制在64K

    因无连接,是不可靠协议

    不需要建立连接,速度快

TCP

    建立连接,形成传输数据的通道//三次握手:你在吗?我在。我知道你在了。  

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

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

必须建立连接,效率会稍低

 

Socket

    Socket就是为网络服务提供的一种机制。

    通信的两端都有Socket

    通信其实就是Socket间的通信。

    数据在两个Socket间通过IO传输。

 

UDP发送端

 

DatagramSocket

DatagramPacket(数据报包)

 

通过udp传输方式,将一段文字数据发送出去。

思路:

1.建立udpsocket服务。

2.提供数据,并将数据封装到数据包中

3.通过socket服务的发送功能,将数据包发送出去。

4.关闭资源。

 

定义一个应用程序,用于接收UDP协议传输的数据并处理。

1.定义udpsocket服务。接收端通常会监听一个端口,其实就是给这个接收网络应用程序定义数字标识。方便于明确哪些数据过来,该程序可以处理。

2.定义一个数据包,因为要存储接收到的字节数据。因为数据包对象有更多的功能提取字节数据中的不同数据信息。

3.通过socket服务的receive方法将收到的数据存入已定义好的数据包中。

4.通过数据包对象的特有功能。将这些不同的数据取出,打印在控制台上。

5.关闭资源

 

TCP传输

 

    SocketServerSocket

    建立客户端和服务器端

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

    关闭Socket

    同样,客户端与服务器端是两个独立的应用程序。

 

代码:

 

package TCPandUDP;

 

import java.net.*;

 

publicclassUdpDemo {

 

    publicstaticvoid main(String[] args) throws Exception

    {

        Threadt1=newThread(newUdpReceive());

        Threadt2=newThread(newUdpSend());

        t1.start();

        t2.start();

    }

 

}

class UdpSend extends Thread

{

    publicvoid run()

    {

        synchronized (UdpSend.class) {

            try {

                DatagramSocketds = newDatagramSocket();//可以指定一个端口

                byte[] buf = "UDP send".getBytes();

                DatagramPacketdp = newDatagramPacket(buf, buf.length,

                        InetAddress.getByName("192.168.1.101"),8000);

                ds.send(dp);

                System.out.println("udp send");

                ds.close();

            }catch(Exception e) {

                e.printStackTrace();

            }

        }

    }

}

class UdpReceive extends Thread

{

    publicvoid run()

    {

       

        synchronized (UdpDemo.class) {

            try {

                DatagramSocketds = newDatagramSocket(8000);//监听端口

                byte[] buf = newbyte[1024];

                DatagramPacketdp = newDatagramPacket(buf, buf.length);

                ds.receive(dp);

                Stringip = dp.getAddress().getHostAddress();

                Stringdata = newString(dp.getData(), 0, dp.getLength());

                int port = dp.getPort();

                System.out.println(ip + "::" + data + "::" + port);

                System.out.println("udp rece");

                ds.close();

            }catch(Exception e) {

                e.printStackTrace();

            }

        }  

    }

}

 

TCP传输

1,tcp分客户端和服务端

2,客户端对应的对象是Socket

服务端对应的对象是ServerSocket

 

客户端

通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机。

因为tcp是面向连接的。所以在建立socket服务时。

就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。

1,创建Socket服务,并指定要连接的主机和端口。

2,获取Socket流中的输出流对象,向流中写入数据,通过网络发送给服务端。

3,关闭客户端资源

 

服务端:

 

1,建立服务端的socket服务,ServerSocket()

并监听一个端口。

2,获取连接过来的客户端对象。

通过ServerSocketaccept方法。没有机会就等,所以这个方法是阻塞式的。

3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据,并打印在控制台。

4,关闭服务器(可选)

 

代码:

package TCPandUDP;

 

import java.io.*;

import java.net.*;

 

publicclassTcpDemo {

 

    publicstaticvoid main(String[] args) throws Exception

    {

        Threadt1=newThread(newTcpServer());

        Threadt2=newThread(newTcpClient());

        t1.start();

        t2.start();

    }

}

class TcpClient extends Thread

{

    publicvoid run()

    {

        try {

            Sockets = newSocket("192.168.1.101", 8002);

            OutputStreamout = s.getOutputStream();

            out.write("Tcp Run".getBytes());

            System.out.println("Client run");

            s.close();

        }catch(Exception e) {

            e.printStackTrace();

        }

    }

}

class TcpServer extends Thread {

 

    publicvoid run()

    {

        try {

            ServerSocketss = newServerSocket(8002);

            Sockets = ss.accept();

            Stringip = s.getInetAddress().getHostAddress();

            System.out.println(ip + "...connected");

            InputStreamin = s.getInputStream();

            byte[] buf = newbyte[1024];

            int len = in.read(buf);

            System.out.println(new String(buf, 0, len));

            s.close();

            ss.close();

        }catch(Exception e) {

            e.printStackTrace();

        }

    }

}

 

多线程上传图片 TCP

 

import java.io.*;

import java.net.*;

 

class piclient

{

    publicstaticvoid main(String[] args) throws Exception

    {  

       if(args.length!=1)

       {

           System.out.println("请传入一张图片!");

           return;

       }

        Filefile=new File(args[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("192.168.1.100",10008);

       FileInputStream fis=new FileInputStream(file);

       byte[] buf =newbyte[1024];

       OutputStream out=s.getOutputStream();

       int len=0;

       while((len=fis.read(buf))!=-1)

       {

           out.write(buf,0,len);

       }

       s.shutdownOutput();//定义结束标记

       InputStream in=s.getInputStream();

       byte[] bufin=newbyte[1024];

       int num=in.read(bufin);

       System.out.println(new String(bufin,0,num));

       fis.close();

       s.close();

    }

}

class PicThreads implements Runnable

{

    private Socket s;

    public PicThreads(Socket s)

    {

       this.s=s;

    }

   

    publicvoid run()

    {

       int count=1;

       String ip=s.getInetAddress().getHostAddress();

       try

       {

           System.out.println(ip+"......connected");

           InputStream in=s.getInputStream();

           File file=new File(ip+"("+(count)+").jpg");//count要加括号,否则下面代码会判断file不存在,不能newFileserver线程结束。

           while(file.exists())

              file=new File(ip+"("+(count++)+").jpg"); 

           FileOutputStream fos=new FileOutputStream(file);

           byte [] buf=newbyte[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)

       {

           thrownew RuntimeException("上传失败!");

       }

    }

}

class piserver

{

    publicstaticvoid main(String[] args) throws Exception

    {

       ServerSocket ss=new ServerSocket(10008);

       while(true)

       {

           Socket s=ss.accept();

           new Thread(new PicThreads(s)).start();       

       }

    }

}

 

 

正则表达式:符合一定规则的表达式。

作用:用于专门操作字符串。

特点:用于一些特定的符号来表示一些代码操作,这样可以简化书写。

所以学习正则表达式,就是在学习一些特殊符号的使用。

 

好处:可以简化对字符串的复杂操作。

弊端:符号定义越多,正则越长,阅读性越差。

 

具体操作功能:APIpattern

1.匹配:String matches 方法,用规则匹配整个字符串,只要有一个不符合规则,就匹配结束,返回false

Stringstr=”ab”;

Stringreg=”[bcd][a-z]”;//第一位是bcd其中一个,第二位a-z中任意一个。

Booleanb=str.matches(reg);

 

Stringstr=”a124235465”;

Stringreg=”[a-z]\\d*”;//\d*数字零次或多次

2.切割:String split();

“.”点表示任意字符  “\.”:按任意字符切  \\. .

代码:splitDemo("erkktyuuuidsfddddop","(.)\\1+")//按叠词完成切割

\\按照叠词完成切割,为了可以让规则的结果被重用,可以将规则封装成一个组,组的出现都有编号。从1开始,想要使用已有的组可以通过\nn就是组的编号)的形式来获取。

 

3.替换:String str.replaeAll(reg,newstr);

Stringstr1=”fdkkdlldfpppp”;//将叠词替换成单个的词

replaceAllDemo(str1,”(.)\\1+”,”$1”);$代表前面的组,n代表第几个组

方法replaceAllDemo(Stringstr,String reg,String,newStr)

4.获取:将字符串中符合规则的字串取出。

 

操作步骤:1.将正则表达式封装成对象。

2.让正则表达式和要操作的字符串相关联。

3.关联后,获取正则匹配引擎。

4.通过引擎对符合规则的字串进行操作,比如取出。

 

代码:

package Regex;

 

import java.util.regex.*;

 

publicclassRegexDemo {

 

    publicstaticvoid main(String[] args)

    {

        getDemo();

    }

    publicstaticvoid getDemo()

    {

        Stringstr="mian tian jiu yao fang jia leda jia";

        Stringreg="\\b[a-z]{3}\\b";// \b单词边界

        //将规则封装成对象

        Patternp=Pattern.compile(reg);

        //让正则对象和要作用的字符串相关联,获取匹配器对象。

        Matcherm=p.matcher(str);

        //System.out.println(m.matches());//其实String类中的matches方法,用的就是PatternMatcher对象来完成的。

                                        //只不过被String的方法封装后,用起来较为简单,但是功能却单一。

//      booleanb=m.find();//将规则作用到字符串上,并进行符合规则的子串查找

//      System.out.println(b);

//      System.out.println(m.group());//用于获取匹配后结果

       

        while(m.find())

        {

            System.out.println(m.group());

            System.out.println(m.start()+"..."+m.end());//获取字符串的角标,包含头,不包含尾

        }

    }

}

 

编程,获取一个文件中包含的邮箱地址:

classRegDemo

{

    public static void main(String[] args)throwsException

    {

       BufferedReader bufr=

              new BufferedReader(newFileReader("D:\\aa.html"));

       String line=null;

       String matchReg=("[a-zA-Z0-9_]{6,16}@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}");

       Pattern p=Pattern.compile(matchReg);

       while((line=bufr.readLine())!=null)

       {

           Matcher m=p.matcher(line);

           while(m.find())

              {

                  System.out.println(m.group());

              }

       }

    }

}

------- android培训、 java培训、期待与您交流! ----------

你可能感兴趣的:(Java编程)