六、TCP

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

一、网络模型1.1、OIS参考模型

1.2、TCP/ip参考模型

1.3、网络通讯要素

IP地址:IPV4/IPV6

端口号:0-65535,一般0-1024,都被系统占用,MySQL:3306,Oracle:1521

传输协议:TCP/UDP

二、类 InetAddress 2.1、InetAddress 主机对象

IP 地址是 IP 使用的 32 位或 128 位无符号数字,它是一种低级协议,UDP 和 TCP 协议都是在它的基础上构建的

2.2、示例

importjava.net.*;classIPDemo

{publicstaticvoidmain(String[] args)throwsException

{//getLoaclHostAddress();getAllByName();

}/*获取本机的IP和主机名*/publicstaticvoidgetLoaclHostAddress()throwsException

{//返回本地主机InetAddress ia=InetAddress.getLocalHost();

System.out.PRintln(ia.toString());//主机名String hostName=ia.getHostName();//IP地址String ip=ia.getHostAddress();

System.out.println("hostName="+hostName+".....ip="+ip);

}/*获取163或者百度的所有IP地址集合*/publicstaticvoidgetAllByName()throwsException

{//获取淘宝的主机数组InetAddress [] ia=InetAddress.getAllByName("www.163.com");for(InetAddress i:ia)

{//输出主机IP地址System.out.println("IP:"+i.getHostAddress());

System.out.println("Name:"+i.getHostName());

}

}

}

三、TCP与UDP3.1、概述

四、Socket4.1、Socket

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

通信两端都有Socket

网络通信其实就是Socket间的通信

数据在两个Socket间通过IO通信

五、UDP

5.1、概述

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

构造方法摘要

DatagramSocket()

构造数据报套接字并将其绑定到本地主机上任何可用的端口。

protected

DatagramSocket(DatagramSocketImpl impl)

创建带有指定 DatagramSocketImpl 的未绑定数据报套接字。

DatagramSocket(int port)

创建数据报套接字并将其绑定到本地主机上的指定端口。

DatagramSocket(int port,

InetAddress laddr)

创建数据报套接字,将其绑定到指定的本地地址。

DatagramSocket(SocketAddress bindaddr)

创建数据报套接字,将其绑定到指定的本地套接字地址。

此类表示数据报包。

数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证。

构造方法摘要DatagramPacket(byte[] buf, int length)

构造DatagramPacket,用来接收长度为length的数据包。

DatagramPacket(byte[] buf,

int length, InetAddress address, int port)

构造数据报包,用来将长度为length的包发送到指定主机上的指定端口号。

DatagramPacket(byte[] buf,

int offset, int length)

构造DatagramPacket,用来接收长度为length的包,在缓冲区中指定了偏移量。

DatagramPacket(byte[] buf,

int offset, int length, InetAddress address, int port)

构造数据报包,用来将长度为length偏移量为offset的包发送到指定主机上的指定端口号。

DatagramPacket(byte[] buf,

int offset, int length, SocketAddress address)

构造数据报包,用来将长度为length偏移量为offset的包发送到指定主机上的指定端口号。

DatagramPacket(byte[] buf,

int length, SocketAddress address)

构造数据报包,用来将长度为length的包发送到指定主机上的指定端口号。

5.2、UDP发送端

/*发送端

1.创建UDP服务,通过DatagramSocekt,

2.创建发送的数据,并封装为数据包,DatagramPacket

3.发送send

4.关闭DatagramSocekt资源*/importjava.net.*;classUdpSend

{publicstaticvoidmain(String[] args)throwsException

{//1.创建UDP服务,通过DatagramSocekt,DatagramSocket ds=newDatagramSocket();//2.创建发送的数据,并封装为数据包,DatagramPacketString say="udp数据!";byte[] buf =say.getBytes();

InetAddress ia=InetAddress.getByName("localhost");intport =9898;

DatagramPacket dp=newDatagramPacket(buf,buf.length,ia,port);//3.发送sendds.send(dp);//4.关闭DatagramSocekt资源ds.close();

}

}

5.3、UDP接收端服务端

/*接收端,服务端

1.创建UDP,Socket服务对象,DatagramSocket,设置商品

2.创建数据服包对象DatagramPacket包,接收数据报包

3.接收receive,到数据包在

4.通过数据报包,获取其中的数据如IP,数据和端口

5.解析数据转化为字符串,并打印

6.关闭资源*/importjava.net.*;classUdpReceive

{publicstaticvoidmain(String[] args)throwsException

{//1.创建UDP,Socket服务对象,DatagramSocket,设置端口DatagramSocket ds=newDatagramSocket(9898);//2.创建数据服包对象DatagramPacket包,接收数据报包//接收内容的字节数据byte[] buf=newbyte[1024];

DatagramPacket dp=newDatagramPacket(buf,buf.length);//3.接收receive,到数据包在ds.receive(dp);//4.通过数据报包,获取其中的数据如IP,数据和端口//IPDString ip=dp.getAddress().getHostAddress();//主机名String hostname=dp.getAddress().getHostName();//数据String data=newString(dp.getData(),0,dp.getLength());//5.解析数据转化为字符串,并打印System.out.println(ip+":"+hostname+":"+data);//6.关闭资源ds.close();

}

}

5.4、键盘录入

/*发送端

键盘录入*/importjava.net.*;importjava.io.*;classUdpSend2

{publicstaticvoidmain(String[] args)throwsException

{//建立UDPSocket服务对象DatagramSocketDatagramSocket ds=newDatagramSocket();//主机对象InetAddress ia=InetAddress.getByName("localhost");intport=10001;//录入数据,字符流,键盘录入BufferedReader br=newBufferedReader(newInputStreamReader(System.in));

String line=null;while((line=br.readLine())!=null)

{if("886".equals(line))

break;//封装为数据报包byte[] buf=line.getBytes();

DatagramPacket dp=newDatagramPacket(buf,buf.length,ia,port);//发送ds.send(dp);

}//关闭

br.close();

ds.close();

}

}

/*接收端一直开启*/importjava.net.*;classUdpRece2

{publicstaticvoidmain(String[] args)throwsException

{//建立DatagramSocket对象服务,并指定端口DatagramSocket ds=newDatagramSocket(10001);while(true)

{//接收数据报包byte[] buf=newbyte[1024];

DatagramPacket dp=newDatagramPacket(buf,buf.length);//接收ds.receive(dp);//获取数据报中的数据String ip=dp.getAddress().getHostAddress();

String data=newString(dp.getData(),0,dp.getLength());

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

}

}

}

5.5、示例

packagecom.pb.demo1;/*简单聊天工具*///发送端importjava.net.*;importjava.io.*;classSendimplementsRunnable

{privateDatagramSocket ds;publicSend( DatagramSocket ds)

{this.ds=ds;

}//线程重写方法publicvoidrun()

{try{//接收键盘录入BufferedReader br=newBufferedReader(newInputStreamReader(System.in));

InetAddress ia=InetAddress.getByName("192.168.2.255");intport =10002;

String line=null;while((line=br.readLine())!=null)

{if("886".equals(line))

break;//封装数据byte[] buf=line.getBytes();

DatagramPacket dp=newDatagramPacket(buf,buf.length,ia,port);//发送ds.send(dp);

}

}catch(Exception e)

{thrownewRuntimeException("发送失败!");

}

}

}//接收端classReceimplementsRunnable

{privateDatagramSocket ds;publicRece( DatagramSocket ds)

{this.ds=ds;

}//线程重写方法publicvoidrun()

{try{while(true)

{//接收byte[] buf=newbyte[1024];

DatagramPacket dp=newDatagramPacket(buf,buf.length);

ds.receive(dp);//通过数据报获取信息String ip=dp.getAddress().getHostAddress();

String data=newString(dp.getData(),0,dp.getLength());//输出System.out.println(ip+":"+data);

}

}catch(Exception e)

{thrownewRuntimeException("接收失败!");

}

}

}classChatDemo

{publicstaticvoidmain(String[] args)throwsException

{//发送DatagramSocket send=newDatagramSocket();//接收DatagramSocket rece=newDatagramSocket(10002);newThread(newSend(send)).start();newThread(newRece(rece)).start();

}

}

六、TCP5.1、概述

5.2、TCP传输一次-简单使用

/*TCP传输

1.TCP分客户端与服务端

2.客户端:Socket

服务端:ServerSocket*//*客户端:

Socket()

通过系统默认类型的 SocketImpl 创建未连接套接字

Socket(InetAddress address, int port)

创建一个流套接字并将其连接到指定 IP 地址的指定端口号。

Socket(InetAddress host, int port, boolean stream)

已过时。 Use DatagramSocket instead for UDP transport.

Socket(InetAddress address, int port, InetAddress localAddr, int localPort)

创建一个套接字并将其连接到指定远程地址上的指定远程端口。

Socket(Proxy proxy)

创建一个未连接的套接字并指定代理类型(如果有),该代理不管其他设置如何都应被使用。

protected Socket(SocketImpl impl)

使用用户指定的 SocketImpl 创建一个未连接 Socket。

Socket(String host, int port)

创建一个流套接字并将其连接到指定主机上的指定端口号。

Socket(String host, int port, boolean stream)

已过时。 使用 DatagramSocket 取代 UDP 传输。

Socket(String host, int port, InetAddress localAddr, int localPort)

创建一个套接字并将其连接到指定远程主机上的指定远程端口。

通过构造方法可以发现:

Socket对象,在建立时,就可以去连接指定主机

因为Tcp是面向连接的,所以在连接成功,形成通路后,

在该通道进行数据的传输

步骤:

1.创建客户端Socket服务,指定主机与端口

2.获取Socket流,socket.getXXX(InputStream或者OutputStream,并封装为字符流或者字节流

3.发送数据

4.关闭socket服务*/importjava.net.*;importjava.io.*;classTcpClient

{publicstaticvoidmain(String[] args)throwsException

{//1.创建客户端Socket服务,指定主机与端口Socket s=newSocket("localhost",10003);//2.获取Socket流,socket.getXXX(InputStream或者OutputStream,并封装为字符流或者字节流OutputStream os=s.getOutputStream();//3.发送数据String say="Tcp客户端发送,测试数据!";

os.write(say.getBytes());//4.关闭socket服务s.close();

}

}/*步骤:

1.创建服务端Socket服务,指定端口

2.监听accept,并获取Socket流,没有连接,这个方法是阻塞工的

3.获取对应客户端对象的socket.getXXX(InputStream或者OutputStream,并封装为字符流或者字节流

4.接收数据InptuStream或者发送OutputStream

5.打印

6.(可选一般不关闭)关闭socket服务*/classTcpServer

{publicstaticvoidmain(String[] args)throwsException

{//1.创建服务端Socket服务,指定端口ServerSocket ss=newServerSocket(10003);//2.监听accept,并获取Socket流,没有连接,这个方法是阻塞工的Socket s=ss.accept();//3.获取对应客户端对象的socket.getXXX(InputStream或者OutputStream,并封装为字符流或者字节流//4.接收数据InptuStream或者发送OutputStreamInputStream is=s.getInputStream();//获取客户端IPString ip=s.getInetAddress().getHostAddress();//设置缓冲区byte[] buf=newbyte[1024];//把数据读取到缓冲区中intlen=is.read(buf);//转换为字符串String data=newString(buf,0,len);//5.打印System.out.println(ip+"........");

System.out.println(data);//6.(可选一般不关闭)关闭socket服务s.close();

ss.close();

}

}

5.3、SocetKet接收与返回

/*客户端给服务端发送数据

服务端收到后给客户端反馈信息

客户接收反馈数据*//*步骤:

1.创建客户端Socket服务,指定主机与端口

2.获取Socket流,socket.getXXX(InputStream或者OutputStream,并封装为字符流或者字节流

3.发送数据

4.关闭socket服务*/importjava.net.*;importjava.io.*;classTcpClient2

{publicstaticvoidmain(String[] args)throwsException

{//1.建立Socekt服务并指定端口Socket s=newSocket("localhost",10004);//2.信息String sendInfo="客户端发送的信息!";//3.获取输出流写到服务端OutputStream os=s.getOutputStream();

os.write(sendInfo.getBytes());//4.获取输入信息接收服务端信息InputStream is=s.getInputStream();byte[] buf=newbyte[1024];intlen=is.read(buf);

String rev=newString(buf,0,len);

System.out.println("服务端反馈的信息:"+rev);

s.close();

}

}/*步骤:

1.创建服务端Socket服务,指定端口

2.监听accept,并获取Socket流,没有连接,这个方法是阻塞工的

3.获取对应客户端对象的socket.getXXX(InputStream或者OutputStream,并封装为字符流或者字节流

4.接收数据InptuStream或者发送OutputStream

5.打印

6.(可选一般不关闭)关闭socket服务*/classTcpServer2

{publicstaticvoidmain(String[] args)throwsException

{//建立服务端ServerSocket数据ServerSocket ss=newServerSocket(10004);//获取客户端对象accept,Socket s=ss.accept();//获取输入流对象接收客户端信息InputStream is=s.getInputStream();//建立缓冲区byte[] buf=newbyte[1024];intlen=is.read(buf);

String clientInfo=newString(buf,0,len);//获取IPString ip=s.getInetAddress().getHostAddress();

System.out.println(ip+"....."+clientInfo);//返回给客户端的信息String rel="已经收到了";//获取输出流对象OutputStream os=s.getOutputStream();

os.write(rel.getBytes());//关闭 可选s.close();

ss.close();

}

}

5.4、综合

/*建立一个转换服务器

客户端输入内容到服务器,服务把内容转成大写再返回给客户端

客户端可以 不断的进行文本输入,

当客户端输入over时结束*//*客户端

操作设备上的数据,可以使用IO技术

并按照IO的操作规律来完成

源:键盘录入

目的:网络设置,网络输出

而且操作的是文本数据,可以选择

字符流与字符缓冲流*/importjava.io.*;importjava.net.*;classTcpClient3

{publicstaticvoidmain(String[] args)throwsException

{//建立服务Socket s=newSocket("localhost",10005);//获取键盘录入BufferedReader br=newBufferedReader(newInputStreamReader(System.in));//目的发送给服务端//BufferedWriter bwOut=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));//打印流,可以接收字符流、缓冲流、字节流,第二个参数true表示自动刷新PrintWriter out=newPrintWriter(s.getOutputStream(),true);//获取服务端返回的信息BufferedReader brIn=newBufferedReader(newInputStreamReader(s.getInputStream()));//键盘录入数据String line=null;//服务端返回数据String recLine=null;//接收键盘录入while((line=br.readLine())!=null)

{if("over".equals(line))

break;

out.println(line);/*//将信息写入服务端

bwOut.write(line);

//增加换行

bwOut.newLine();

//刷新缓冲区

bwOut.flush();*///获取取服务端返回的大写数据recLine=

brIn.readLine();

System.out.println("服务器返回信息:"+recLine);

}//结束,关资源s.close();

}

}/*服务器*/classTcpServer3

{publicstaticvoidmain(String[] args)throwsException

{//建立服务端对象ServerSocket ss=newServerSocket(10005);//获取客户端Socket对象Socket s=ss.accept();

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

System.out.println(ip+"....");//获取客户端流对象BufferedReader brIn=newBufferedReader(newInputStreamReader(s.getInputStream()));//BufferedWriter bwOut=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));//打印流,可以接收字符流也可以接收字节流,加true自动刷新PrintWriter out=newPrintWriter(s.getOutputStream(),true);

String line=null;while((line=brIn.readLine())!=null)

{

System.out.println("客户端说:"+line);

out.println(line.toUpperCase());/*//转换为大写返回客户端

bwOut.write(line.toUpperCase());

//增加换行

bwOut.newLine();

//刷新缓冲区

bwOut.flush();*/}

s.close();

ss.close();

}

}/*问题:

客户端和服务端都在莫名的等待

因为客户端和服务端都在阻塞的方法,

这些方法没有读到结束标记,那么就一直等待

而导致两端,都在等待*/

5.5、示例-TCP文件复制

/*上传一个文件到服务器*/importjava.net.*;importjava.io.*;/*客户端*/classUploadClient

{publicstaticvoidmain(String[] args)throwsException

{//建立客户端服务Socket s=newSocket("localhost",10009);//上传文件File file=newFile("d:\\gm.mp3");//获取文件名String filename=file.getName();//建立基本数据流将文件名发送过去PrintWriter pw=newPrintWriter(s.getOutputStream(),true);//发送pw.println(filename);//建立输入流FileInputStream fis=newFileInputStream(file);

BufferedInputStream bis=newBufferedInputStream(fis);//建立流输出BufferedOutputStream bos=newBufferedOutputStream(s.getOutputStream());//建立字符缓冲,接收服务端返回的提示信息BufferedReader br=newBufferedReader(newInputStreamReader(s.getInputStream()));intlen=0;while((len=bis.read())!=-1)

{

bos.write(len);

bos.flush();

}//关闭输出流,增加结束标记s.shutdownOutput();

String str=

br.readLine();

System.out.println(str);

bis.close();

fis.close();

s.close();

}

}/*服务端*/classUploadServer

{publicstaticvoidmain(String[] args)throwsException

{//建立服务ServerSocket ss=newServerSocket(10009);//获取客户端对象Socket s=ss.accept();//获取客户端 发送的文件名BufferedReader br=newBufferedReader(newInputStreamReader(s.getInputStream()));

String filename=

br.readLine();

System.out.println("文件名:"+filename);//文件输读流BufferedInputStream bis=newBufferedInputStream(s.getInputStream());//文件输出流File f=newFile("f:\\",filename);

BufferedOutputStream bos=newBufferedOutputStream(newFileOutputStream(f));//输出提示信息PrintWriter pw=newPrintWriter(s.getOutputStream(),true);intlen=0;while((len=bis.read())!=-1)

{

bos.write(len);

bos.flush();

}

pw.println("上传成功");

bos.close();

s.close();

ss.close();

}

}

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航