网络编程

------- android培训、java培训、期待与您交流! ----------
网络编程:
 |----用到net包一般会用到io包
 |----程序在通信时的步骤:
  1.先找到对方IP。
  2.数据要发送到对方指定的应用程序上,为了标示这些程序,给网络程序都用了数字标示
  为了方便称呼这些数字,叫做端口。网线连接的是物理端口,网卡给网络程序分配的数字标示
  叫做逻辑端口。
   |----计算机的端口范围是从0号端口到65535号端口。端口0~1023为系统的端口。用于标示进程的逻辑地址
   |----WEB用的是80端口
  3.定义通信规则。这个通信规则称之为协议。国际组织定义了通用协议TCP/IP.
  A与B之间通信要装有相同的协议才可以识别,有些组织为了安全,他们有自己特定的协议来进行
  内部通信。
  |----公网不用的地址(保留):
  127.0.0.1本机回环地址,可以ping他来测试网卡。localhost
  192.168.0.*;局域网
 |----OSI模型:
  |----数据封包:
   |----数据从顶层开始一层一层的封装
   |----物理层:红外,光纤,蓝牙
  |----数据拆包:
   |----从底层开始一层一层的拆装,每一层都在读他能识别的数据,到顶层后根据端口来
    将数据送给网络应用程序。
  |----每一层都有自己的规则,传输层最常见的是TCP和UDP,网际层最常见的是IP,应用层最常见HTTP,FTP
 |----UDP协议
  |----面向无连接
  |----将数据,IP地址,端口封装成数据包,不需要建立连接,因为省略了确定对象是否存在这一步,所以速度比较快
   他不需要建立连接。如果IP地址不存在,或者端口关闭则将包丢弃。
  |----每个数据包的大小限制在64K
  |----因为不建立连接所以时不可靠协议,通常用于不重要信息的传输比如聊天,网络视频,丢包不影响。但是下载视频是TCP
   如果少了数据可能解析不出。
 |----TCP协议
  |----面向连接形成数据的传输通道
  |----可以进行大数据的传输
  |----通过三次握手建立连接是可靠协议。A-->B(a向b发送数据确定其是否存在)B-->A(b回应数据,a确定b的存在)
   A-->B( a又想b发送数据,说收到b的回应 )这样就建立了可靠的连接
 |----Socket(插座的意思,也叫套接字)编程,也就是网络编程。网络程序之间的接口
  |----字符串和字节数组的转换String s. s.getBytes();字符串转为字节数组  byte[] b. new String(b);按照默认编码将字节转换为字符串
  |----Socket就是为网络服务提供的一种机制
  |----通信的两端都有Socket
  |----网络通信其实就是Socket之间的通信
  |----数据在两个Socket之间通过IO传输
  |----DatagramSocket
   |----此类表示用来发送和接收数据报包的套接字
   |----void send(DatagramPacket p) 他其中的send方法发送的就是数据报包对象
  |----DatagramPacket
   |----数据报包,用来实现无连接包投递服务。
   |----里面封装了源地址,源端口,目的地址,目的端口。构造DatagramPacket对象是如果有参数InetAddress就是数据发送
 
TCP传输:
 |----UDP传输分发送端和接收端,TCP分客户端和服务端,用到的对象为Socket,ServerSocket
 |----TCP是面向连接的,所以对象在建立的时候需要指定目标地址,通路已建立,就产生了Socket流
  这个流是随着连接的产生而建立的,不需要去创建,可以通过方法得到流中的输入输出对象。
 |----服务端在处理多个客户端的请求时用的是各个客户端的流对象,这样处理不会产生混乱。
 import java.io.*;
 import java.net.*;
 class SocketDemo
 {
  public static void main(String[] args) throws Exception
  {
   //Socket s = new Socket( InetAddress.getByName( "192.168.0.1" ), 11000 );
   Socket s = new Socket(  "192.168.0.11", 11000 );//可以直接用字符串来确定目标地址
   //到的这个套接字的输出流,用来将数据写入流中
   OutputStream out = s.getOutputStream();
   out.write( "woshi123".getBytes() );
   //如果服务端没及时反馈,那么客户端的读取流会一直等到服务端反馈,阻塞
   InputStream in = s.getInputStream();
   byte[] b = new byte[1024];
   int len = in.read(b);
   System.out.println( new String( b, 0, len ) );
   s.close();
  }
 }
 class  ServerDemo
 {
  public static void main(String[] args) throws Exception
  {
   //建立一个服务端并绑定该服务端监听的端口
   ServerSocket ss = new ServerSocket(11000);
   //侦听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。
   Socket s = ss.accept();
   //用的是客户端的Socket对象
   InputStream in = s.getInputStream();//用客户端的Scoket中的读取方法读取流中的数据
   //byte[] b = in.read();读取单个字节
   //InetAddress getInetAddress() 客户端的Socket中封装了客户端的地址InetAddress
   byte[] b = new byte[1024];
   int len = in.read(b);
   System.out.println( s.getInetAddress().getHostAddress()+"...."+new String( b, 0, len ) );
   //向客户端反馈信息
   Thread.sleep( 10000 );
   OutputStream out = s.getOutputStream();
   out.write( "woshi789".getBytes() );
   //关闭客户端,断开连接,防止客户端一直占用服务端的资源
   s.close();
   //服务端也有自己的关闭方法,不过服务端一般都是一直开启的
  }
 }
|----用服务端将客户端发送的数据转换成大写
 1.写入Socket流也刷新
 2.结束标志的。在键盘录入时尤其重要
 3.PrintWriter简化操作
 4.步骤
import java.io.*;
import java.net.*;
class MySendSocket
{
 public static void main(String[] args) throws Exception
 {
  BufferedReader r = new BufferedReader( new InputStreamReader( System.in ) );
  Socket s = new Socket( "192.168.0.11", 12000 );
  BufferedWriter w = new BufferedWriter( new OutputStreamWriter( s.getOutputStream() ) );
  BufferedReader br = new BufferedReader( new InputStreamReader( s.getInputStream() ) );
  String line = null;
  while( ( line = r.readLine() ) != null )
  {
   if( "over".equals( line ) )
    break;//客户端关闭。则流关闭,流关闭则流中在读取数据会是-1,服务端中的readLine()底层方法是read读到-1也会结束
     //结束后执行关闭服务端
   w.write( line );
   w.newLine();//为了服务端能够识别文件结尾需要加上换行
   w.flush();//Socket流也是先将数据写到了缓冲区,也需要刷新
   System.out.println( line+"::"+br.readLine() );
  }
  r.close();
  s.close();
 }
}
class MyServerSocket
{
 public static void main(String[] args)  throws Exception
 {
  ServerSocket ss = new ServerSocket( 12000 );
  Socket s = ss.accept();
  System.out.println( s.getInetAddress().getHostAddress()+"connected" );
  BufferedReader r = new BufferedReader( new InputStreamReader( s.getInputStream() ) );
  //BufferedWriter w = new BufferedWriter( new OutputStream( s.getOutputStream() ) );
  PrintWriter pw = new PrintWriter( s.getOutputStream(), true );
  String line = null;
  while( ( line = r.readLine() ) != null )//如果客户端将数据写入流中时没有加换行,则这里会一直读第一句
  {
   if( "over".equals(line) )
    break;
   System.out.println( line );
   pw.println( line.toUpperCase() );//打印流不关闭是因为s.close()将输出流关闭了?
   //关闭该流并释放与之关联的所有系统资源。关闭以前关闭的流无效。API的描述
  }
  s.close();//服务端要关一次客户端
  ss.close();
 }
}
|----TCP上传文件到服务端,服务端将文件存储,并反馈给客户端一个信息告诉客户端上传成功
****注意事项:客户端在读取文件时读到文件流的结尾处停止循环,停止循环后等待服务端的反馈,这时客户端流没有关闭
 服务端结束的标志是以客户端的Socket流中的标志来结束的,Socket流没有结束则不能结束循环。客户端和服务端都陷入等待中。
 有两种解决方法:
 1.加一个自定义标志,但是如果是文本文件用字符串比如"over"如果文本中也有over会导致文件没有传完服务端停止。
 可以用时间戳的方式,在Socket流开头部分加入一个long time = System.currentTimeMillis();在客户端结束文件发送后在在流末尾
 发送一个time服务端的循环中判断流中是否有和开头相同的time信息,有就结束循环。long的读取用DataInputStream.
 2.用Socket中的方法shutdownInput()在Socket流中添加一个EOF
 3.阻塞式方法和while一起用
 |----传送图片到服务端,服务器可以处理多个连接
 import java.net.*;
import java.io.*;
class PicSend
{
 public static void main(String[] args) throws Exception
 {
  if( args.length != 1 )
  {
   System.out.println( "请输入一个jpg图片的路径" );
   return;
  }
  File f = new File( args[0] );
  if( !( f.exists() & f.isFile() ) )
  {
   System.out.println( "文件不存在或者文件不是一个图片" );
  }
  if( !f.getName().endsWith( ".jpg" ) )
  {
   System.out.println( "图片不是jpg格式" );
  }
  if( f.length() > 1024*1024*5 )
  {
   System.out.println( "文件过大" );
  }
  BufferedInputStream bis = new BufferedInputStream( new FileInputStream(f) );//这里要try要是没有读取成功下面的也不需要执行了
  byte[] buf = new byte[1024*1024];
  Socket s = new Socket( "192.168.0.11", 13000 );//这里也要try一个,如果连接没有成功下面的也不需要执行
  //PrintStream ps = new PrintStream( s.getOutputStream() );println带自动刷新,并且print不能限制打印数组的长度
  //FileOutputStream fos = s.getOutputStream();函数返回的是一个OutputStream对象不能用fos接收,还是用PrintStream吧
  //PrintStream ps = new PrintStream( s.getOutputStream() );虽然OutputStream不可以new对象但是可以接收对象,就像接口也可以接收对象一样
  OutputStream out = s.getOutputStream();
  BufferedReader r = new BufferedReader( new InputStreamReader( s.getInputStream() ) );
  int len = 0;
  while( ( len = bis.read( buf ) ) != -1 )
  {
   out.write( buf, 0, len );
  }
  s.shutdownOutput();//给流加上结束标志
  System.out.println( r.readLine() );
  bis.close();
  s.close();
 }
}
class PicRece
{
 public static void main(String[] args) throws Exception
 {
  ServerSocket ss = new ServerSocket( 13000 );//貌似服务端在执行多线程时不管几个连接都一个端口
  //服务器软件有一个固定的端口
  while( true )
  {
   Socket s = ss.accept();//建立一个连接则创建一个对象,服务端用的是客户端的套接字流对象
   new Thread( new Server(s) ).start();
  }
 }
}
class Server implements Runnable
{
 private Socket s;
 Server( Socket s )
 {
  this.s = s;
 }
 public void run()
 {
  try
  {
   int count = 1;
   String hostName = s.getInetAddress().getHostAddress();
   File f = new File( hostName+".jpg" );
   while( f.exists() )
   {
    f = new File( hostName+"("+(count++)+")"+".jpg" );
   }
   FileOutputStream fos = new FileOutputStream( f );//应该从客户端得到文件的名字,如果重名的文件则加(1)
   byte[] buf = new byte[1024*1024];
   System.out.println( hostName+"...connected" );
   BufferedInputStream bis = new BufferedInputStream(s.getInputStream());//返回的是一个抽象的类型
   //建立流对象将发送成功的信息反馈给客户端
   BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(s.getOutputStream()) );
   int len = 0;
   //将客户端传送的文件写入服务端
   while( ( len = bis.read(buf) ) != -1 )
   {
    fos.write( buf, 0, len );
   }
   //反馈给客户端信息
   bw.write( "图片已经发送" );
   bw.newLine();//一定要记得加上结束标志
   bw.flush();//一定要记得刷新
   //关闭资源
   fos.close();
   s.close();
   System.out.println( hostName+"...断开连接" );
  }
  catch ( Exception e )
  {
   throw new RuntimeException( "上传失败" );
  }
 }
}
 ------- android培训、java培训、期待与您交流! ----------   详细请查看: http://edu.csdn.net/heima/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值