Java基础--网络编程之TCP

来源:互联网 发布:java 导入excel xlsx 编辑:程序博客网 时间:2024/05/22 12:44


凌风博客原创作品。转载请注明出处:

演示tcp传输

1.tcp分客户端和服务端
2.客户端对应的对象时Socket

  服务端对应的对象时ServerSocket



客户端
通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机
因为tcp是面向连接的,所以在建立socket服务时
就要有服务端存在,并连接成功,形成通路后,在该通道进行数据的传输

需求:给服务端发送一个文本数据

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

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. import java.io.*;  
  2. import java.net.*;  
  3. class TcpClient  
  4. {  
  5.     public static void main(String[] args) throws Exception  
  6.     {  
  7.         //创建客户端的socket服务,指定目的主机和端口  
  8.         Socket s = new Socket("192.168.1.102",10003);  
  9.           
  10.         //为了发送数据,应该获取socket流中的输出流  
  11.         OutputStream out = s.getOutputStream();  
  12.           
  13.         out.write("tcp ge men lai le ".getBytes());//将数据写入到输出流中  
  14.   
  15.         s.close();  
  16.     }  
  17. }  

需求:定义端点接收数据并打印在控制台上


服务端:
1.建立服务端的socket服务,ServerSocket();
  并监听一个端口
2.获取连接过来的客户端对象
  通过ServerSocket的 accept方法,没有连接就会等,所以这个方法是阻塞式的。
3.客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据
  并打印在控制台
4.关闭服务端(可选操作)。

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class TcpServer  
  2. {  
  3.     public static void main(String[] args) throws Exception  
  4.     {  
  5.         //建立服务端Socket服务,并监听一个端口  
  6.         ServerSocket ss = new ServerSocket(10003);  
  7.   
  8.         //通过accept方法获取连接过来的客户端对象  
  9.         Socket s = ss.accept();  
  10.   
  11.         String ip = s.getInetAddress().getHostAddress();  
  12.         System.out.println(ip+".....connected");  
  13.   
  14.         //获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。  
  15.         InputStream in = s.getInputStream();  
  16.   
  17.         byte[] buf = new byte[1024];  
  18.         int len = in.read(buf);  
  19.   
  20.         System.out.println(new String(buf,0,len));  
  21.   
  22.         s.close(); //关闭客户端  
  23.   
  24.         ss.close(); //关闭服务端  
  25.     }  
  26. }  

演示tcp的传输的客户端和服务端的互访。


需求:客户端给服务端发送数据,服务端收到后,给客户端反馈信息。



客户端
1.建立socket服务,指定要连接主机和端口
2.获取socket流中的输出流,将数据写入到该流中,通过网络发送给服务端
3.获取socket流中的输入流,将服务端反馈的数据获取到,并打印
4.关闭客户端资源

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class TcpClient   
  2. {  
  3.     public static void main(String[] args) throws Exception  
  4.     {  
  5.         Socket s = new Socket("192.168.1.102",10004);  
  6.   
  7.         OutputStream out = s.getOutputStream();  
  8.   
  9.         out.write("服务端,你好".getBytes());  
  10.           
  11.         //接收服务端反馈回来的数据  
  12.         InputStream in = s.getInputStream();  
  13.   
  14.         byte[] buf = new byte[1024];  
  15.   
  16.         int len = in.read(buf);  
  17.   
  18.         System.out.println(new String(buf,0,len));  
  19.   
  20.         s.close();  
  21.     }  
  22. }  
  23.   
  24.   
  25. class TcpServer  
  26. {  
  27.     public static void main(String[] args) throws Exception  
  28.     {  
  29.         ServerSocket ss = new ServerSocket(10004);  
  30.   
  31.         Socket s = ss.accept();  
  32.   
  33.         String ip = s.getInetAddress().getHostAddress();  
  34.         System.out.println(ip+"....connected");  
  35.   
  36.         InputStream in = s.getInputStream();  
  37.   
  38.         byte[] buf = new byte[1024];  
  39.   
  40.         int len = in.read(buf);  
  41.   
  42.         System.out.println(new String(buf,0,len));  
  43.   
  44.         OutputStream out = s.getOutputStream();  
  45.         //发送反馈数据给客户端  
  46.         out.write("哥们收到,你也好".getBytes());  
  47.   
  48.         s.close();  
  49.   
  50.         s.close();  
  51.     }  
  52. }  

需求:建立一个文本转换服务器
客户端给服务端发送文本,服务端会将文本转成大写再返回给客户端
而且客户端可以不断的进行文本转换,当客户端输入over时,转换接收


分析:
客户端
既然是操作设备上的数据,那么就可以使用IO技术,并按照io的操作规律来思考
源:键盘录入
目的:网络设备,网络输出流
而且操作的是文本数据,可以选择字符流


步骤:
1.建立服务
2.获取键盘录入
3.将数据发给服务端
4.获取服务端返回的大写数据
5.结束,管资源


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

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. import java.io.*;  
  2. import java.net.*;  
  3. class TransClient  
  4. {  
  5.     public static void main(String[] args) throws Exception  
  6.     {  
  7.         Socket s = new Socket("192.168.1.102",10005);  
  8.   
  9.         //定义读取键盘数据的流对象  
  10.         BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));  
  11.   
  12.         //定义目的,将数据写入到socket输出流,发给服务端  
  13.         //BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));  
  14.           
  15.         PrintWriter out = new PrintWriter(s.getOutputStream(),true);  
  16.   
  17.         //定义一个socket读取流,读取服务端返回的大写信息  
  18.         BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));  
  19.   
  20.         String line = null;  
  21.   
  22.         while ((line=bufr.readLine())!=null)  
  23.         {  
  24.             if("over".equals(line))  
  25.                 break;  
  26.               
  27.             out.println(line);  
  28.             //bufOut.write(line);  
  29.             //bufOut.newLine();  
  30.             //bufOut.flush();  
  31.   
  32.             String str = bufIn.readLine();  
  33.   
  34.             System.out.println("server:"+str);  
  35.         }  
  36.   
  37.         bufr.close();  
  38.         s.close();  
  39.     }  
  40. }  
  41.   
  42. /* 
  43. 服务端: 
  44. 源:socket读取流 
  45. 目的:socket输出流 
  46. 都是文本,装饰 
  47. */  
  48.   
  49. class TransServer  
  50. {  
  51.     public static void main(String[] args) throws Exception  
  52.     {  
  53.         ServerSocket ss = new ServerSocket(10005);  
  54.   
  55.         Socket s = ss.accept();  
  56.         String ip = s.getInetAddress().getHostAddress();  
  57.         System.out.println(ip+"....conneted");  
  58.   
  59.         //读取socket读取流中的数据  
  60.         BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));  
  61.   
  62.         //目的,socket输出流,将大写数据写入到socket输出流,并发送给客户端,  
  63.         //BufferedWriter bufOut = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));  
  64.           
  65.         PrintWriter out = new PrintWriter(s.getOutputStream(),true);  
  66.   
  67.         String line = null;  
  68.           
  69.         //客户端停下来之后服务端就停下来了,是因为客户端读到s.close();时,返回-1.当readLine()读到-1时也就停下里了。  
  70.         while ((line=bufIn.readLine())!=null)//readLine判断一行结束的标记是回车符  
  71.         {  
  72.             System.out.println(line);  
  73.             out.println(line.toUpperCase());  
  74.             //bufOut.write(line.toUpperCase());  
  75.             //bufOut.newLine();  
  76.             //bufOut.flush();  
  77.   
  78.         }  
  79.   
  80.         s.close();  
  81.         ss.close();  
  82.     }  
  83. }  
  84.   
  85. /* 
  86. 该例子出现的问题。 
  87. 现象:客户端和服务端都在莫名的等待 
  88. 为什么呢? 
  89. 因为客户端和服务端都有阻塞式方法,这些方法没有读到结束标记。那么就一直等 
  90. 而导致两端都在等待 
  91.  
  92. */  

上传文件

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. import java.io.*;  
  2. import java.net.*;  
  3. class TextClient  
  4. {  
  5.     public static void main(String[] args) throws Exception  
  6.     {  
  7.         Socket s = new Socket("192.168.1.102",10006);  
  8.   
  9.         BufferedReader bufr = new BufferedReader(new FileReader("TcpDemo_5.java"));  
  10.   
  11.         PrintWriter out = new PrintWriter(s.getOutputStream(),true);  
  12.           
  13.         //使用标记作为结束标记  
  14.         //DataOutputStream dos = new DataOutputStream(s.getOutputStream());  
  15.         //long time = System.currentTimeMillis();  
  16.         //out.println(time);  
  17.         //dos.writeLong(time);  
  18.   
  19.         String line = null;  
  20.         while ((line=bufr.readLine())!=null)  
  21.         {  
  22.             out.println(line);  
  23.         }  
  24.   
  25.         s.shutdownOutput();//关闭客户端的输出流,相当于给流中加入一个结束标记-1  
  26.   
  27.         //dos.writeLong(time);  
  28.   
  29.         BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));  
  30.   
  31.         String str = bufIn.readLine();  
  32.         System.out.println(str);  
  33.   
  34.         bufr.close();  
  35.         s.close();  
  36.     }  
  37. }  
  38.   
  39.   
  40. class TextServer  
  41. {  
  42.     public static void main(String[] args) throws Exception  
  43.     {  
  44.         ServerSocket ss = new ServerSocket(10006);  
  45.   
  46.         Socket s = ss.accept();  
  47.   
  48.         String ip = s.getInetAddress().getHostAddress();  
  49.         System.out.println(ip+"....conneted");  
  50.   
  51.         BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));  
  52.           
  53.         PrintWriter out = new PrintWriter(new FileWriter("server.txt"),true);  
  54.   
  55.         String line = null;  
  56.         while ((line=bufIn.readLine())!=null)  
  57.         {  
  58.               
  59.             out.println(line);  
  60.         }  
  61.   
  62.         PrintWriter pw = new PrintWriter(s.getOutputStream(),true);  
  63.         pw.println("上传成功");  
  64.   
  65.         out.close();  
  66.         s.close();  
  67.         ss.close();  
  68.   
  69.     }  
  70. }  

上传图片


客户端
1.服务端点
2.读取客户端已有的图片数据
3.通过socket输出流将数据发给服务端
4.读取服务端反馈信息
5.关闭

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. import java.io.*;  
  2. import java.net.*;  
  3. class PicClient  
  4. {  
  5.     public static void main(String[] args) throws Exception  
  6.     {  
  7.         if (args.length!=1)  
  8.         {  
  9.             System.out.println("请选择一个jpg格式的图片.");  
  10.             return ;  
  11.         }  
  12.   
  13.         File file = new File(args[0]);  
  14.   
  15.         if (!(file.exists() && file.isFile()))  
  16.         {  
  17.             System.out.println("该文件有问题,要么不存在要么不是文件");  
  18.             return ;  
  19.         }  
  20.   
  21.         if (!file.getName().endsWith(".jpg"))  
  22.         {  
  23.             System.out.println("图片格式错误,请重新选择");  
  24.             return ;  
  25.         }  
  26.   
  27.         if (file.length()>1024*1024*5)  
  28.         {  
  29.             System.out.println("文件过大");  
  30.             return ;  
  31.         }  
  32.   
  33.           
  34.   
  35.         Socket s = new Socket("192.168.1.102",10007);  
  36.   
  37.         FileInputStream fis = new FileInputStream(file);  
  38.   
  39.         OutputStream out = s.getOutputStream();  
  40.   
  41.         byte[] buf = new byte[1024];  
  42.   
  43.         int len = 0;  
  44.   
  45.         while ((len=fis.read(buf))!=-1)  
  46.         {  
  47.             out.write(buf,0,len);  
  48.         }  
  49.   
  50.         //告诉服务端数据已写完  
  51.         s.shutdownOutput();  
  52.           
  53.         //接收反馈信息  
  54.         InputStream in = s.getInputStream();  
  55.   
  56.         byte[] bufIn = new byte[1024];  
  57.   
  58.         int num = in.read(bufIn);  
  59.   
  60.         System.out.println(new String(bufIn,0,num));  
  61.   
  62.         fis.close();  
  63.         s.close();  
  64.     }  
  65. }  

服务端
这个服务端有个局限性,当A客户端连接上以后,被服务端获取到,服务端执行具体流程
这时B客户端连接,只有等待
因为服务端还没有处理完A客户端的请求,还没有循环回来执行下次accept方法,所以
暂时获取不到B客户端对象


那么为了可以让多个客户端同时并发访问服务端
那么服务端最好就是将每个客户端封装到一个单独的线程中,这样,就是可以同时处理多个客户端请求。




如何定义线程呢?


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

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class PicThread implements Runnable  
  2. {  
  3.     private Socket s;  
  4.     PicThread(Socket s)  
  5.     {  
  6.         this.s = s;  
  7.     }  
  8.   
  9.     public void run()  
  10.     {  
  11.         String ip = s.getInetAddress().getHostAddress();  
  12.           
  13.         try  
  14.         {  
  15.             int count = 1;  
  16.             System.out.println(ip+"....connected");  
  17.               
  18.             InputStream in = s.getInputStream();  
  19.   
  20.             //防止文件名重复使用IP(count),作为文件名  
  21.             File file = new File(ip+"("+(count)+")"+".jpg");  
  22.   
  23.             while(file.exists())  
  24.                 file = new File(ip+"("+(count++)+")"+".jpg");  
  25.   
  26.               
  27.             FileOutputStream fos = new FileOutputStream(file);  
  28.   
  29.             byte[] buf = new byte[1024];  
  30.   
  31.             int len = 0;  
  32.   
  33.             while ((len=in.read(buf))!=-1)  
  34.             {  
  35.                 fos.write(buf,0,len);  
  36.             }  
  37.   
  38.             OutputStream out = s.getOutputStream();  
  39.   
  40.             out.write("上传成功".getBytes());  
  41.   
  42.             fos.close();  
  43.   
  44.             s.close();  
  45.         }  
  46.         catch (Exception e)  
  47.         {  
  48.             throw new RuntimeException(ip+"上传失败");  
  49.         }  
  50.     }  
  51. }  
  52.   
  53.   
  54. class PicServer   
  55. {  
  56.     public static void main(String[] args) throws Exception  
  57.     {  
  58.         ServerSocket ss = new ServerSocket(10007);  
  59.           
  60.         while (true)  
  61.         {  
  62.             Socket s = ss.accept();  
  63.               
  64.             //将获取到的方法传给PicThread中的run方法执行,以达到多用户同时上传  
  65.             new Thread(new PicThread(s)).start();  
  66.         }  
  67.           
  68.   
  69.         //ss.close();  
  70.     }  
  71. }  

客户端通过键盘录入用户名。
服务端对这个用户名进行效验


如果该用户存在,在服务端显示xxx,已登录
并在客户端显示 xxx,欢迎观临


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


最多就登陆三次

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. import java.io.*;  
  2. import java.net.*;  
  3. class  LoginClient  
  4. {  
  5.     public static void main(String[] args) throws Exception  
  6.     {  
  7.         Socket s = new Socket("192.168.1.102",10008);  
  8.   
  9.         BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));  
  10.           
  11.         //将数据发给服务端的写入流  
  12.         PrintWriter out = new PrintWriter(s.getOutputStream(),true);  
  13.           
  14.         //读取服务端发过来的信息的读取流  
  15.         BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));  
  16.   
  17.         for (int x = 0;x<3 ;x++ )  
  18.         {  
  19.             String line = bufr.readLine();//读取键盘录入  
  20.   
  21.             if(line==null)  
  22.                 break;  
  23.   
  24.             out.println(line);//将键盘数据写入到给服务端的写入流  
  25.   
  26.             String info = bufIn.readLine();//读取服务端发来的信息  
  27.   
  28.             System.out.println("info"+info);  
  29.   
  30.             if(info.contains("欢迎"))  
  31.                 break;  
  32.         }  
  33.   
  34.         bufr.close();  
  35.   
  36.         s.close();  
  37.     }  
  38. }  
  39.   
  40.   
  41. class UserThread implements Runnable  
  42. {  
  43.     private Socket s;  
  44.     UserThread(Socket s)  
  45.     {  
  46.         this.s = s;  
  47.     }  
  48.   
  49.     public void run()  
  50.     {  
  51.         String ip = s.getInetAddress().getHostAddress();  
  52.         System.out.println(ip+"....connected");  
  53.         try  
  54.         {  
  55.             for (int x = 0;x<3 ;x++ )  
  56.             {  
  57.                 //读取客户端传过来的姓名  
  58.                 BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));  
  59.   
  60.                 String name = bufIn.readLine();  
  61.                 if(name==null)  
  62.                     break;  
  63.   
  64.                 BufferedReader bufr = new BufferedReader(new FileReader("user.txt"));  
  65.                   
  66.                 //获取写入流对象,负责反馈数据  
  67.                 PrintWriter out = new PrintWriter(s.getOutputStream(),true);  
  68.   
  69.                 String line = null;  
  70.   
  71.                 boolean flag = false;  
  72.                 while ((line=bufr.readLine())!=null)//读取文件中的用户进行比较  
  73.                 {  
  74.                     if (line.equals(name))  
  75.                     {  
  76.                         flag = true;  
  77.                         break;  
  78.                     }  
  79.                 }  
  80.   
  81.                 if (flag)  
  82.                 {  
  83.                     System.out.println(name+",已登录");  
  84.                     out.println(name+",欢迎光临");  
  85.                     break;  
  86.                 }  
  87.                 else  
  88.                 {  
  89.                     System.out.println(name+",尝试登陆");  
  90.                     out.println(name+",用户名不存在");  
  91.                 }  
  92.   
  93.             }  
  94.             s.close();  
  95.         }  
  96.         catch (Exception e)  
  97.         {  
  98.             throw new RuntimeException(ip+"效验失败");  
  99.         }  
  100.     }  
  101. }  
  102.   
  103.   
  104. class LoginServer  
  105. {  
  106.     public static void main(String[] args) throws Exception  
  107.     {  
  108.         ServerSocket ss = new ServerSocket(10008);  
  109.   
  110.         while (true)  
  111.         {  
  112.             Socket s = ss.accept();  
  113.   
  114.             new Thread(new UserThread(s)).start();  
  115.         }  
  116.     }  
  117. }  

0 0