欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

黑马程序员----java基础--网络编程(1)(3)

来源: javaer 分享于  点击 25559 次 点评:277

三、TCP协议-客户端和服务端

客户端Client)首先与服务端Server)建立连接,形成通道其实就是IO流),然后,数据就可以在通道之间进行传输,并且单个Server端可以同时与多个Client端建立连接。Socket和ServerSocket,建立客户端和服务器端。建立连接后,通过Socket中的IO流进行数据的传输。关闭socket。同样,客户端与服务器端是两个独立的应用程序。

TCP客户端

客户端需要明确服务器的ip地址以及端口,这样才可以去试着建立连接,如果连接失败,会出现异常。连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已经提供了输入流和输出流对象,通过getInputStream()和getOutputStream()获取即可与服务端通讯。结束后关闭Socket。客户端,通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机。因为tcp是面向连接的。所以在建立socket服务时,就要有服务端存在,并连接成功。形成通路后,在该通道进行数据的传输。

TCP服务端

服务端需要明确它要处理的数据是从哪个端口进入的。当有客户端访问时,要明确是哪个客户端,可通过accept()获取已连接的客户端对象,并通过该对象与客户端通过IO流进行数据传输。当该客户端访问结束,关闭该客户端。1,建立服务端的socket服务。ServerSocket();并监听一个端口。2,获取连接过来的客户端对象。通过ServerSokcet的 accept方法。没有连接就会等,所以这个方法阻塞式的。3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。并打印在控制台。4,关闭服务端。可选)。

TCP协议因为是面向连接的。所以传输数据必须先开服务端,再开客户端。否则,客户端根本连接不上服务端。

1、Socket类中常用方法

(1)、构造方法

1 new Socket();
2 new Socket(InetAddress address,int port);//创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
3 new Socket(String host,int port);// 创建一个流套接字并将其连接到指定主机上的指定端口号。

(2)、成员方法

  1. void  bind(SocketAddress bindpoint);//将套接字绑定到本地地址。  
  2. void  connect(SocketAddress endpoint);//将此套接字连接到服务器。  
  3. InetAddress  getInetAddress();//返回套接字连接的地址。 
  4. InputStream  getInputStream();//返回此套接字的输入流。 
  5. OutputStream  getOutputStream();// 返回此套接字的输出流。  
  6. int  getPort();// 返回此套接字连接到的远程端口  
  7. void  shutdownInput();// 此套接字的输入流置于“流的末尾”。  
  8. void  shutdownOutput();// 禁用此套接字的输出流 

2、ServerSocket类中常用方法

(1)、构造方法

1 new ServerSocket();//创建非绑定服务器套接字。
2 new ServerSocket(int port);//创建绑定到特定端口的服务器套接字。

(2)、成员方法

1 Socket accept();//侦听并接受到此套接字的连接。
2 InetAddress getInetAddress();// 返回此服务器套接字的本地地址。

需求:TCP协议-服务端和客户端交互代码演示:

  1. import java.io.*; 
  2. import java.net.*; 
  3. class  TCPClient 
  4.     public static void main(String[] args) throws Exception 
  5.     { 
  6.         //创建客户端的socket服务。指定目的主机和端口 
  7.         Socket s=new Socket("192.168.1.100",5544); 
  8.         //为了发送数据,应该获取socket流中的输出流。 
  9.         OutputStream out=s.getOutputStream(); 
  10.         out.write("TCP,我来了!".getBytes()); 
  11.         InputStream in=s.getInputStream(); 
  12.         byte[] buf=new byte[1024]; 
  13.         int len=in.read(buf); 
  14.         System.out.println(new String(buf,0,len)); 
  15.         s.close(); 
  16.     } 
  17. class TCPServer 
  18.     public static void main(String[] args)throws Exception{ 
  19.         //建立服务端socket服务。并监听一个端口。 
  20.         ServerSocket ss=new ServerSocket(5544); 
  21.         //通过accept方法获取连接过来的客户端对象。 
  22.         Socket s=ss.accept(); 
  23.         //获取ip地址 
  24.         String ip=s.getInetAddress().getHostAddress(); 
  25.         System.out.println(ip+".....connnect"); 
  26.         //获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。 
  27.         InputStream in=s.getInputStream(); 
  28.         byte[] buf=new byte[1024]; 
  29.         int len=in.read(buf); 
  30.         System.out.println(new String(buf,0,len)); 
  31.  
  32.         OutputStream out=s.getOutputStream(); 
  33.         out.write("收到".getBytes()); 
  34.         ss.close(); 
  35.         //关闭客户端. 
  36.         s.close(); 
  37.     } 

需求:建立一个文本转换服务器。

客户端给服务端发送文本,服务单会将文本转成大写在返回给客户端。而且客户度可以不断的进行文本转换。当客户端输入over时,转换结束。

客户端:

既然是操作设备上的数据,那么就可以使用io技术,并按照io的操作规律来思考。

源:键盘录入。

目的:网络设备,网络输出流。

而且操作的是文本数据。可以选择字符流。

步骤

1,建立服务。

2,获取键盘录入。

3,将数据发给服务端。

4,后去服务端返回的大写数据。

5,结束,关资源。

都是文本数据,可以使用字符流进行操作,同时提高效率,加入缓冲。

服务端:

源:socket读取流。

目的:socket输出流。

都是文本,装饰。

  1. import java.io.*; 
  2. import java.net.*; 
  3. class TransClient  
  4.     public static void main(String[] args) throws Exception 
  5.     { 
  6.         Socket s=new Socket("192.168.1.100",7788); 
  7.         //定义读取键盘数据的流对象。 
  8.         BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 
  9.         //定义目的,将数据写入到socket输出流。发给服务端。 
  10.         PrintWriter out=new PrintWriter(s.getOutputStream(),true); 
  11.         //定义一个socket读取流,读取服务端返回的大写信息。 
  12.         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 
  13.         String line=null
  14.         while ((line=br.readLine())!=null
  15.         { 
  16.             out.println(line); 
  17.             if("over".equals(line)) 
  18.                 break
  19.             String info=in.readLine();         
  20.             System.out.println("info="+info); 
  21.         } 
  22.         s.close(); 
  23.  
  24.     } 
  25. class TransServer 
  26.     public static void main(String[] args)throws Exception{ 
  27.         ServerSocket ss=new ServerSocket(7788);         
  28.         Socket s=ss.accept(); 
  29.         System.out.println(s.getInetAddress().getHostAddress()+".....connect"); 
  30.         //读取socket读取流中的数据。 
  31.         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 
  32.         //目的。socket输出流。将大写数据写入到socket输出流,并发送给客户端。 
  33.         PrintWriter out=new PrintWriter(s.getOutputStream(),true); 
  34.         String line=null
  35.         while ((line=in.readLine())!=null
  36.         { 
  37.             System.out.println(line); 
  38.             out.println(line.toUpperCase()); 
  39.             if("over".equals(line)) 
  40.                 break
  41.         } 
  42.         s.close(); 
  43.         ss.close(); 
  44.     } 

需求:TCP协议上传文本文件

  1. import java.io.*; 
  2. import java.net.*; 
  3. class  TCPClient 
  4.     public static void main(String[] args)throws Exception 
  5.     { 
  6.         Socket s=new Socket("192.168.1.100",9999); 
  7.         BufferedReader br=new BufferedReader(new FileReader("TCPDemo.java")); 
  8.         PrintWriter out=new PrintWriter(s.getOutputStream(),true); 
  9.         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 
  10.         String line=null
  11.         while ((line=br.readLine())!=null
  12.         { 
  13.             out.println(line); 
  14.         } 
  15.         s.shutdownOutput();//关闭客户端的输出流。相当于给流中加入一个结束标记-1. 
  16.         System.out.println(in.readLine()); 
  17.         s.close(); 
  18.         br.close(); 
  19.     } 
  20. class TCPServer 
  21.     public static void main(String[] args)throws Exception{ 
  22.         ServerSocket ss=new ServerSocket(9999); 
  23.         Socket s=ss.accept(); 
  24.         System.out.println(s.getInetAddress().getHostAddress()+"....connect"); 
  25.         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 
  26.         PrintWriter pw=new PrintWriter(new FileWriter("E:\\TCPDemo.java"),true); 
  27.         PrintWriter out=new PrintWriter(s.getOutputStream(),true); 
  28.         String line=null
  29.         while ((line=in.readLine())!=null
  30.         { 
  31.             pw.println(line); 
  32.         } 
  33.         out.println("上传成功"); 
  34.         s.close(); 
  35.         ss.close(); 
  36.         pw.close(); 
  37.     } 

需求:TCP客户端并发上传图片代码演示:

服务端最好就是将每个客户端封装到一个单独的线程中,这样,就可以同时处理多个客户端请求。

如何定义线程呢?

只要明确了每一个客户端要在服务端执行的代码即可。将该代码存入run方法中。

  1. import java.io.*; 
  2. import java.net.*; 
  3. class PicClient 
  4.     public static void main(String[] args)throws Exception{ 
  5.         File file=new File(args[0]); 
  6.         if(!(file.exists()&& file.isFile())){ 
  7.             System.out.println("请上传图片"); 
  8.             return
  9.         } 
  10.         if(!(file.getName().endsWith(".jpg"))){ 
  11.             System.out.println("上传格式错误"); 
  12.             return
  13.         } 
  14.         if(file.length()>=1024*1024*4){ 
  15.             System.out.println("文件过大,请切割后上传"); 
  16.             return
  17.         } 
  18.  
  19.         Socket s=new Socket("192.168.1.104",5555); 
  20.         FileInputStream fis=new FileInputStream(file); 
  21.         OutputStream out=s.getOutputStream(); 
  22.         byte[] buf=new byte[1024]; 
  23.         int len=0
  24.         while ((len=fis.read(buf))!=-1
  25.         { 
  26.             out.write(buf,0,len); 
  27.         } 
  28.         s.shutdownOutput();//告诉服务端数据已写完 
  29.         InputStream in=s.getInputStream(); 
  30.         byte[] bufIn=new byte[1024]; 
  31.         int num=in.read(bufIn); 
  32.         System.out.println(new String(bufIn,0,num)); 
  33.         s.close(); 
  34.         fis.close(); 
  35.     } 
  36. class PicThread implements Runnable 
  37.     private Socket s; 
  38.     PicThread(Socket s){ 
  39.         this.s=s; 
  40.     } 
  41.     public void run(){ 
  42.         String ip=s.getInetAddress().getHostAddress(); 
  43.         System.out.println(ip+".....connect"); 
  44.         try 
  45.         { 
  46.             int count=1
  47.             //创建file对象 
  48.             File file=new File("E:\\"+ip+"("+count+")"+".jpg"); 
  49.             //如果file文件存在则count++,直到不存在为止 
  50.             while(file.exists()) 
  51.                 file=new File("E:\\"+ip+"("+(count++)+")"+".jpg"); 
  52.             InputStream in=s.getInputStream(); 
  53.             FileOutputStream fos=new FileOutputStream(file); 
  54.             byte[] buf=new byte[1024]; 
  55.             int len=0
  56.             while ((len=in.read(buf))!=-1
  57.             { 
  58.                 fos.write(buf,0,len); 
  59.             } 
  60.             OutputStream out=s.getOutputStream(); 
  61.             out.write("上传成功".getBytes()); 
  62.             s.close();             
  63.         } 
  64.         catch (Exception e) 
  65.         { 
  66.             System.out.println(ip+"连接成功"); 
  67.         } 
  68.     } 
  69. class PicServer 
  70.     public static void main(String[] args)throws Exception{ 
  71.         ServerSocket ss=new ServerSocket(5555); 
  72.         while (true
  73.         { 
  74.             Socket s=ss.accept(); 
  75.             new Thread(new PicThread(s)).start(); 
  76.         } 
  77.     } 

需求:客户端通过键盘录入用户名。服务端对这个用户名进行校验。最多就登录三次。

如果该用户存在,在服务端显示xxx,已登陆。

并在客户端显示 xxx,欢迎光临。

如果该用户不存在,在服务端显示xxx,尝试登陆。

并在客户端显示 xxx,该用户不存在。

  1. import java.io.*; 
  2. import java.net.*; 
  3. class LoginClient  
  4.     public static void main(String[] args)throws Exception 
  5.     { 
  6.         Socket s=new Socket("192.168.1.104",6666); 
  7.         BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 
  8.         //读取socket流中的读取流 
  9.         BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 
  10.         //socket流中的输出流 
  11.         PrintWriter out=new PrintWriter(s.getOutputStream(),true);     
  12.         //循环3次输入,如果输入为null,直接停止输入 
  13.         for (int x=0;x<3 ;x++ ) 
  14.         { 
  15.             String name=br.readLine(); 
  16.             if(name==null
  17.                 break
  18.             out.println(name); 
  19.             String info=in.readLine(); 
  20.             System.out.println(info); 
  21.             //如果获取到流中有“欢迎“字样,说明对方已经登录,这时候即使输入的不到3次,也停止输入,因为已经登录成功了。 
  22.             if(info.contains("欢迎")){                 
  23.                 break
  24.             } 
  25.         } 
  26.         s.close(); 
  27.     } 
  28. class LoginThread implements Runnable 
  29.     private Socket s; 
  30.     LoginThread(Socket s){ 
  31.         this.s=s; 
  32.     } 
  33.     public void run(){ 
  34.         String ip=s.getInetAddress().getHostAddress(); 
  35.         System.out.println(ip+".....connect"); 
  36.         try 
  37.         {                 
  38.             for (int x=0;x<3 ;x++ ) 
  39.             { 
  40.                 //读取socket流中的输入流 
  41.                 BufferedReader in=new BufferedReader(new InputStreamReader(s.getInputStream())); 
  42.                 String name=in.readLine(); 
  43.                 if(name==null
  44.                     break
  45.                 //读取文件 
  46.                 BufferedReader br=new BufferedReader(new FileReader("Userinfo.txt")); 
  47.                 //socket流输出流 
  48.                 PrintWriter out=new PrintWriter(s.getOutputStream(),true);     
  49.                 //定义一个标记, 从socket输入流中的键盘数据判断user.txt中是否有name符合,如果有标记为真,跳出while循环。 
  50.                 boolean flag=false
  51.                 String line=null
  52.                 while ((line=br.readLine())!=null
  53.                 { 
  54.                     //判断Userinfo.txt和name是否有相同的 
  55.                     if(line.equals(name)){ 
  56.                         flag=true
  57.                         break
  58.                     } 
  59.                 } 
  60.                 if(flag){ 
  61.                     System.out.println(name+",已登陆"); 
  62.                     out.println(name+",欢迎光临"); 
  63.                     break
  64.                 } 
  65.                 else
  66.                     System.out.println(name+",尝试登陆"); 
  67.                     out.println(name+",该用户不存在"); 
  68.                 } 
  69.             } 
  70.             s.close(); 
  71.         } 
  72.         catch (Exception e) 
  73.         { 
  74.             System.out.println(ip+"连接失败"); 
  75.         } 
  76.     } 
  77. class LoginServer 
  78.     public static void main(String[] args)throws Exception{ 
  79.         ServerSocket ss=new ServerSocket(6666); 
  80.         while (true
  81.         { 
  82.             Socket s=ss.accept(); 
  83.             new Thread(new LoginThread(s)).start(); 
  84.         } 
  85.     } 




相关栏目:

用户点评