毕向东之网络编程Tcp与UDP

/*网络编程:通讯三要素:IP地址,端口号,传输协议
IP地址不易记忆,可用主机名(localhost)<相当于酒店名,也相当于电脑>
端口号<相当于酒店里的房间号,电脑上某个软件>
传输协议:UDP(如发消息,不需要对方连接),TCP(如打电话,必须要对方连接)
UDP特点:将数据封装成包,每个包的大小限制在64K内,不需要建立连接,是不可靠协议,但速度快
TCP特点:建立连接,形成传输数据的通道,
    在连接中进行大数据传输,通过三次握手完成连接,是可靠协议(叫<在吗>,应<在>,回<知道了>)
    必须建立连接,效率会稍低
Socket(插座):就是为网络服务提供的一种机制,通信的两端都有Socket(相当于码头,两台电脑传输的桥梁)
    网络通信其实就是Socket之间的通信
那么UDP的Socket服务怎么建立呢?
DatagramSocket:此类表示用来发送和接收数据报包的套接字。(用于接收发送)
DatagramPacket:此类表示数据报包, 数据报包用来实现无连接包投递服务(用于数据打包,包裹发到哪去必须给出IP和端口)

需求:通过UDP传输方式,将一段文字数据发送出去。
步骤:1.建立UDPSocket服务。2.提供数据,并将数据打包。
3.通过Socket服务的发送功能将数据包发出去。4.关闭资源 
 */
import java.net.*;
class Udpsend{//发送
    public static void main(String[] args)throws Exception{
        InetAddress inetd=InetAddress.getLocalHost();
        System.out.println(inetd.getHostAddress());//获取主机地址
        System.out.println(inetd.getHostName());//获取主机名称
        DatagramSocket ds=new DatagramSocket(888);//建立UDPSocket服务,没有定义服务站端口名系统会自动添加一个
        byte[] buf="数据来了".getBytes();
        //提供数据,并将数据打包。确定发送到的IP和端口名
        DatagramPacket ap=new DatagramPacket(buf,buf.length,InetAddress.getByName(inetd.getHostName()),1720);
        ds.send(ap);//将数据包发出去
        ds.close();//关闭资源
    }
}
//用于接收发出端口发来的数据
class Udpreceive{//接收
    public static void main(String[] args)throws Exception{
        //定义Socket服务接收 接收哪个发来的呢?所以要定义服务站的端口名且与发送端一致才能接收到
        DatagramSocket ds=new DatagramSocket(1720);//端口为1720,端口知道绑定一个Socket
        //定义字节数组存放数据
        byte[] buf=new byte[1024];
        DatagramPacket dp=new DatagramPacket(buf,buf.length);
        //通过服务的receive方法将收到的数据存入数据包中
        ds.receive(dp);//阻塞式方法,没数据就等
        //通过数据包的方式获取其中的数据
        int len=dp.getLength();//数据的长度
        String data=new String(dp.getData(),0,len);//获取接收的数据
        int port=dp.getPort();//获取发送端的端口号
        String ip=dp.getAddress().getHostAddress();//返回 IP地址字符串
        System.out.println(ip+"---"+data+"---"+port);
        ds.close();//关闭服务站
    }
}

 

 

//阻塞式方法
import java.net.*;
import java.io.*;
class Udpsend2{//发送
    public static void main(String[] args) throws Exception{
        DatagramSocket ds=new DatagramSocket(888);
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String line;
        String ip=InetAddress.getLocalHost().getHostName();
        while((line=br.readLine())!=null){
            if(line.equals("886"))
                break;
            byte[] arr=line.getBytes();//变为字节数组发送出去(发送就要指明地点和数据)
            DatagramPacket dp=new DatagramPacket(arr,arr.length,InetAddress.getByName(ip),1000);
            ds.send(dp);
        }
        ds.close();
    }
}
class Udpreceive2{//接收
    public static void main(String[] args)throws Exception{
        DatagramSocket ds=new DatagramSocket(1000);
        while(true){//不停的接收
            byte[] arr=new byte[1024];
            DatagramPacket dp=new DatagramPacket(arr,arr.length);//用来存储数据
            ds.receive(dp);//接收数据
            byte[] data=dp.getData();//只有一部分是接收到的数据
            String textdata=new String(data,0,dp.getLength());//将数组arr一部分转换为字符串数据
            System.out.println(dp.getAddress()+"--"+dp.getPort()+"--:"+textdata);
        }
    }
}

 

 

/*需求:自己电脑既能接收数据又能发送数据
 127.0.0.1为我电脑的IP
 .1改为.255代表播放频段,局域网中只要开着端口就能就收到数据
 */
import java.net.*;
import java.io.*;
public class Test3 {
    public static void main(String[] args) throws Exception{
        Thread t1=new Thread(new Receive(new DatagramSocket(101)));
        Thread t2=new Thread(new Send(new DatagramSocket(88)));
        t1.start();//先走接收
        t2.start();
    }
}
class Send implements Runnable{//发送
    private DatagramSocket sd;
    public Send(DatagramSocket sd){
        this.sd=sd;
    }
    public void run(){
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String line;
        try{
            while((line=br.readLine())!=null){
                if(line.equals("886"))
                    break;
                byte[] arr=line.getBytes();
                String ip=InetAddress.getLocalHost().getHostName();
                DatagramPacket dp=new DatagramPacket(arr,arr.length,InetAddress.getByName("127.0.0.255"),101);
                sd.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{
            byte[] arr=new byte[1024];
            DatagramPacket dp=new DatagramPacket(arr,arr.length);
            while(true){
                ds.receive(dp);
                byte[] tata=dp.getData();
                String text=new String(tata,0,dp.getLength());
                System.out.println(dp.getAddress()+"-:"+text);
            }
        }catch(Exception e){
            throw new RuntimeException("接收失败");
        }
    }
}

 

 

 /* TCP传输包括:由客户端(Socket)和服务端(ServerSocket)
连接后通过Socket中的IO流进行数据的传输
需求:客服端向服务端发送一文本信息,服务端接收到后向客服端回一信息
此题注意点:当读数据用readLine方法时,读完一行会继续读,使得程序一直读回写不了信息
因为readLine即是阻塞式方法,结束标志必须是没有数据,所以结束不了
 */
import java.net.*;
import java.io.*;
class TcpServer{//伺候客户的服务端
    public static void main(String[] args)throws Exception{
        //创建服务端,且指明接收的端口号
        ServerSocket ss=new ServerSocket(10000);
        //获取连接过来的客服端对象
        Socket s=ss.accept();//阻塞式方法,等待连接
        String ip=s.getInetAddress().getHostName();//获取连过来的IP
        System.out.println(ip+"连上了");
        //获取输入输出流
        OutputStream out=s.getOutputStream();
        BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(out));
        InputStream in=s.getInputStream();
        BufferedReader bufr=new BufferedReader(new InputStreamReader(in));
        //读客户端发来的数据
        char[] arr=new char[1024];
        int len=bufr.read(arr);
        System.out.println(new String(arr,0,len));
        //向客户端发数据
        bufw.write("在");
        bufw.newLine();//因为客户端的读数据是一行行读,如果没有换行标记会一直读,因为没有结束标记
        bufw.flush();
    }
}
class TcpSocket{//客户端
    public static void main(String[] args)throws Exception{
        //创建客户端,且指明需要连接的服务端和端口
        Socket s=new Socket("127.0.0.1",10000);
        OutputStream out=s.getOutputStream();
        BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(out));
        InputStream in=s.getInputStream();
        BufferedReader bufr=new BufferedReader(new InputStreamReader(in));
        //客户端发送数据
        bufw.write("服务端,在吗?");
        bufw.newLine();
        bufw.flush();
        //客户端接收服务端发来的数据
        char[] arr=new char[1024];
        int len=bufr.read(arr);
        System.out.println(new String(arr,0,len));
        s.close();
    }
}

 

 

/*需求:建立一个文本转换服务器,客服端给服务端发送文本,服务端会将文本转换成大写再返回给客服端
容易出现的问题:客服端和服务端都在莫名的等待
因为客服端和服务端都有阻塞式方法,这些方法没有读到结束标记,那么就一直等待,导致两端都在等待
 */
import java.net.*;
import java.io.*;
class TCPSocket2{//客服端
    public static void main(String[] args)throws Exception{
        Socket s=new Socket(InetAddress.getLocalHost().getHostAddress(),100);
        BufferedReader bufr=new BufferedReader(new InputStreamReader(s.getInputStream()));
        BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
        String line;
        while((line=in.readLine())!=null){//-1 或换行标记时才结束循环
            if(line.equals("over"))
                break;
            bufw.write(line);//将键盘录入数据发送给服务端
            bufw.newLine();//为服务端提高数据结束标记
            bufw.flush();//将数据刷出去
            String str=bufr.readLine();//读客服端发来的数据
            System.out.println(str);
        }
        s.close();//当关闭时,客服端读方法会有个结束标记-1
        in.close();
    }
}
class TCPServer2{//服务端
    public static void main(String[] args)throws Exception{
        ServerSocket ss=new ServerSocket(100);
        Socket s=ss.accept();
        System.out.println(s.getInetAddress().getHostAddress()+"连上来了");
        BufferedReader bufr=new BufferedReader(new InputStreamReader(s.getInputStream()));
        BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        String str;
        while((str=bufr.readLine())!=null){//接收客服端发来的数据,当客服端关闭后读数据会有结束标记
            bufw.write(str.toUpperCase());//转换为大写发出去
            bufw.newLine();//为接受端提供读结束标记
            bufw.flush();
        }
    }
}

 

 

/*需求:实现文件的发送
 */
import java.io.*;
import java.net.*;
class TcpSocket6{
    public static void main(String[] args)throws Exception{
        Socket s=new Socket(InetAddress.getLocalHost().getHostAddress(),100);
        BufferedReader bufr=new BufferedReader(new InputStreamReader(s.getInputStream()));
        PrintWriter ps=new PrintWriter(s.getOutputStream(),true);//自动刷新且换行
        BufferedReader filer=new BufferedReader(new FileReader("E:\\学习文件\\fuzhi.java"));
        String line;
        while((line=filer.readLine())!=null){//读文本有结束标记
            ps.println(line);//将读到的数据发送给服务端
        }//避免出现双方等待的现象,
        s.shutdownOutput();//关闭写,相当于给服务端的readLine方法一个结束的标记(-1)
        String str=bufr.readLine();//读服务端发来的信息
        System.out.println(str);
        s.close();filer.close();
    }
}
class TcpServer6{
    public static void main(String[] args)throws Exception{
        ServerSocket ss=new ServerSocket(100);
        Socket s=ss.accept();
        System.out.println(s.getInetAddress().getHostAddress()+"..连接上了");
        BufferedReader bufr=new BufferedReader(new InputStreamReader(s.getInputStream()));
        PrintWriter pw=new PrintWriter(s.getOutputStream(),true);
        PrintWriter filew=new PrintWriter(new FileWriter("E:\\学习文件\\1.txt"));
        String line;
        while((line=bufr.readLine())!=null){//读发来的数据,结束标记为shutdownOutput()
            filew.println(line);
        }
        pw.println("传输成功");
        filew.close();
    }
}

 

 

/*需求:实现多人向服务端发送图片
因为服务端要处理多个对象的连接,所以必须要用到线程
 */
import java.io.*;
import java.net.*;
public class Test7 {
    public static void main(String[] args)throws Exception{
        ServerSocket ss=new ServerSocket(100);
        while(true){//服务器原理
            Socket s=ss.accept();
            new Thread(new TcpServer7(s)).start();
        }
    }
}
class TcpServer7 implements Runnable{
        private Socket ss;//服务端获取的连接对象
        public TcpServer7(Socket ss){
            this.ss=ss;
        }
        public void run(){
            try{
                int count=1;
                BufferedInputStream bufi=new BufferedInputStream(ss.getInputStream());
                BufferedOutputStream bufo=new BufferedOutputStream(ss.getOutputStream());
                String ip=ss.getInetAddress().getHostAddress();
                File file=new File("F:\\图片\\"+ip+"("+count+")"+".jpg");
                while(file.exists()){
                    count++;
                    file=new File("F:\\图片\\"+ip+"("+count+")"+".jpg");
                }
                BufferedOutputStream fileout=new BufferedOutputStream(new FileOutputStream(file));
                byte[] arr=new byte[1024];
                int len;
                while((len=bufi.read(arr))!=-1){
                    fileout.write(arr, 0, len);
                    fileout.flush();
                }
                bufo.write(new String("传输成功").getBytes());
                bufo.flush();
                ss.shutdownOutput();
            }catch(Exception e){
                
            }
        }
}
class TcpSocket7{//客服
    public static void main(String[] args)throws Exception{
        File file=new File(args[0]);//编译时传args[0]
        BufferedInputStream fileo=new BufferedInputStream(new FileInputStream(file));//读取指定目录
        Socket s=new Socket("127.0.0.1",100);
        BufferedInputStream bufi=new BufferedInputStream(s.getInputStream());
        BufferedOutputStream bufo=new BufferedOutputStream(s.getOutputStream());
        byte[] arr=new byte[1024];
        int len;
        while((len=fileo.read(arr))!=-1){
            bufo.write(arr,0,len);
            bufo.flush();
        }
        s.shutdownOutput();//写结束
        len=bufi.read(arr);
        System.out.println(new String(arr,0,len));
        s.close();
        fileo.close();
    }
}

 

 

/*模拟IE浏览器—服务器

 */
import java.io.*;
import java.net.*;
public class Test8 {//模拟服务端
    public static void main(String[] args)throws Exception {
        ServerSocket ss=new ServerSocket(101);
        Socket s=ss.accept();
        System.out.println(s.getInetAddress().getHostAddress()+"...连接成功");
        BufferedInputStream bufi=new BufferedInputStream(s.getInputStream());
        byte[] arr=new byte[1024];
        //int len=bufi.read(arr);//获取浏览器发来的信息
        //System.out.println(new String(arr,0,len));
/*接收到的浏览器发来的数据 http://127.0.0.1:100/Test1.java  主机端口的资源
GET /Test1.java HTTP/1.1    http代表协议
Accept: text/html, application/xhtml+xml,  代表能接收的类型
Accept-Language: zh-CN    简体中文
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
UA-CPU: AMD64    用户信息
Accept-Encoding: gzip, deflate    支持的封装形式(解压)
Host: 127.0.0.1:100
Connection: Keep-Alive  连接保持存活
         */
        PrintStream ps=new PrintStream(s.getOutputStream(),true);
        BufferedReader bufr=new BufferedReader(new FileReader("F:\\QQ文件\\my.html"));
        String str;
        while((str=bufr.readLine())!=null){
            ps.println(str);//向浏览器发送数据
        }
        s.shutdownOutput();
        s.close(); 
        ss.close();
    }
}
class URLSocket{//客服端
    public static void main(String[] args)throws Exception{
        URL u=new URL("http://127.0.0.1:101/my.html");//连接资源封装成对象
        URLConnection con=u.openConnection();//URL所引用的远程对象的连接。
        System.out.println(con);
        InputStream in=con.getInputStream();
    }
    
}

 

posted @ 2016-05-31 12:53  ts-android  阅读(299)  评论(0编辑  收藏  举报