javase_22(TCP的学习-->)
来源:互联网 发布:什么是网络恐怖主义 编辑:程序博客网 时间:2024/06/06 12:25
TCP传输
Socket(客户端)和ServerSocket(服务端)
1.建立客户端和服务器端
2.建立连接后,通过Socket中的IO流进行数据的传输
3.关闭Socket()当关闭这个流,其实就是把底层的流所关闭
同样,客户端与服务器端程序是两个独立运行的应用程序.
基本思路:(客户端)
客户端需要明确服务器的IP地址和端口,这样才可以试图去建立连接.如果连接失败,会出现异常.
连接成功,说明客户端与服务器端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已经提供了输入流和输出流对象,通过
getInputStream(), getOutputStream()获取即可.
与服务端通信结束,关闭Socket.
基本思路:(服务器端)
服务端需要明确它要处理的数据是从那个端口进入的.
当有客户端访问时,要明确是那个客户端,可通过accept()获取已经连接的客户端对象,并且通过该对象与客户端通过IO流进行数据的传输.
当客户端访问结束,关闭该客户端.
生动的比喻:
必须要建立114服务台,客户才可以拨打的道理..当TCP服务器程序运行到ServerSocket.accept方法等待客户的连接,在正常的情况下,accept方法会发生阻塞,一直等到客户连接请求的到来.该方法才会返回.如果没有客户端请求来的情况下,accept方法没有发生阻塞,那么肯定前面的程序是有问题的.,通常端口被其他的程序所占用.
利用循环从客户端里面读取数据,并且在服务端显示出来?不要把问题那么复杂,该多线程就多线程-->该怎么走.比喻用到多线程.-->休息一下.等待它读取数据.要不然.我都还没有读取数据.-->你这边就已经执行了.
客户端
通过Socket建立对象并指定要连接的服务端主机与端口
Socket s = new Sockte("127.0.0.0.1",8888);InputStream ips = s.getInputStream();OutputStream ops = s.getOutputStream();S.close();//底层的流必须要关闭/.
服务端:
建立服务端需要监听的一个端口:
ServerSocket ss = new ServerSocket(8888);//获取到客户端的Socket .Socket ss = Ss.accept();InputStream ips = s.getInputStream();OutputStream ops = s.getOutputStream();byte [] buf = new byte[1024];Ips.read(buf);int num = ips.read(buf);String str = new String(buf,0,num);Ss.close();S.close();
简单的TCP客户端与服务端:
客户端:
package com.javami.kudyDemo.Tcp;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;public class TcpClient{/** * 客户端 */public static void main(String[] args){Socket socket = null;try{//连接到指定的主机端口号上socket = new Socket("127.0.0.1",8888);//-->读取服务端的数据InputStream ips = socket.getInputStream();//-->发送服务端的数据OutputStream ops = socket.getOutputStream();ops.write("服务器你最近还好吗?".getBytes());//转换成字节流ops.write("可以同时写两个数据吗??".getBytes());//转换成字节流byte [] buf = new byte[ips.available()];ips.read(buf);System.out.println(new String(buf));}catch(IOException e){}finally{try{if(socket!=null)socket.close();}catch(IOException e){e.printStackTrace();}}}}
服务端:
package com.javami.kudyDemo.Tcp;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class TcpServer{/* * 服务端 */public static void main(String[]args){ServerSocket ss = null;;Socket socket = null;try{ss = new ServerSocket(8888);socket = ss.accept();//监听端口--->和客户端已经绑定起来InputStream ips = socket.getInputStream();OutputStream ops = socket.getOutputStream();byte[] buf = new byte[ips.available()];//个数为多少ips.read(buf);System.out.println(new String(buf));ops.write("我最近过得还好~你不需要担心我服务器的寿命".getBytes());}catch(IOException e){
一个程序开启了多线程-->Thread-0线程去执行..-->Main线程也在执行的.
必须让main线程等待一下.让其有一个消化的过程.
字母的转换:(使用了多线程解决问题)
客户端类
package com.javami.kudyDemo.Tcp;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.Socket;import java.net.UnknownHostException;public class ReverseClinet{public static void main(String[]args) throws InterruptedException, UnknownHostException, IOException{Socket socket = null;socket = new Socket("127.0.0.1",8888);InputStream ips = socket.getInputStream();OutputStream ops = socket.getOutputStream();//接收欢迎语,必须要先休息一下.因为那边写入数据.如果不休息.//由于是开了线程执行的.main主线程就打印出来.所以打印到你的内容必定是空白的Thread.sleep(10);int len = ips.available();byte[] buf = new byte[len];ips.read(buf);System.out.println(new String(buf));BufferedReader br = new BufferedReader(new InputStreamReader(System.in));System.out.println("开始吧!!");while(true){String line = br.readLine();ops.write((line+"\r\n").getBytes());//写入进去int l = ips.available();byte[] b = new byte[l];Thread.sleep(10);ips.read(b);System.out.println(new String(b));}}}
服务端:
package com.javami.kudyDemo.Tcp;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;/* * 服务器提供字符反向服务 *多线程的思路: *我等待用户的连接..当有用户连接.我交给别的线程去执行.对象是仍然没有变.-->socket重点. *必须要循环监听.如果不循环监听...当一个服务端和客户端再运行..我就结束了.. */public class ReverseServer{public static void main(String[]args){ServerSocket ss = null;try{ ss = new ServerSocket(8888);while(true){Socket socket = ss.accept();new Thread(new ReverseServers(socket)).start();}} catch (IOException e){// TODO Auto-generated catch blocke.printStackTrace();}finally{if(ss!=null)try{ss.close();} catch (IOException e){// TODO Auto-generated catch blocke.printStackTrace();}}}}-->它的哥们package com.javami.kudyDemo.Tcp;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.Socket;public class ReverseServers implements Runnable{Socket socket ;public ReverseServers(Socket socket){this.socket = socket;}public void run(){try{InputStream ips = socket.getInputStream();OutputStream ops = socket.getOutputStream();ops.write("启动服务器提供反转功能:".getBytes());while(true){BufferedReader br =new BufferedReader(new InputStreamReader(ips));//把读取到的数据转换成字符流String line = br.readLine();if("quit".equals(line))break;StringBuilder sb = new StringBuilder(line);String newLine = sb.reverse().toString();//转换ops.write(newLine.getBytes());}}catch(IOException e){e.printStackTrace();}finally{if(socket!=null)try{socket.close();} catch (IOException e){// TODO Auto-generated catch blocke.printStackTrace();}}}}
TCP网络程序的工作原理:
TCP客户端程序与TCP服务端程序的交互过程:
1.服务器端程序创建一个ServerSocket,然后调用accpept方法等待客户来连接.
2.客户端程序创建一个Socket并请求服务端建立连接.
3.服务器端接收客户的连接请求,并创建一个新的Socket与该客户建立专线连接.
4.建立了连接的两个Socket在一个单独的线程(由服务端程序创建)上对话.
5.服务器端开始等待i新的连接请求,当新的连接请求到达时,重复上述过程.
文件上传案例分析
一、需求分析
1.多线程的服务器
2.客户端程序
3.上传文件名
4.上传文件
二、实现步骤
1.实现多线程服务器
1)创建ServerSocket对象,监听指定的端口,7888
2)循环调用accept方法,等待客户端的连接,次方法阻塞,返回一个客户端Socket
3)开启新线程,运行一个服务对象,将socket给这个对象
2.实现客户端程序
1)创建Socket对象,连接服务器 127.0.0.1 7888
3.发送和接收欢迎语
服务器端: 获得输入输出流, 发送欢迎语, out.write();
客户端: 获得输入输出流, 接收欢迎语, in.read();
4.发送文件名,创建文件
1)客户端:
读键盘,获得文件路径名 BufferedReader
创建文件对象, File
判断文件是否存在,文件是否为标准文件 isFile
获得文件名:getName
将文件名上传给服务器,out.write
等待接收服务器反馈的信息
2)服务器端:
接收文件名,in.read();
创建文件对象, 在指定目录下创建 createNewFile
判断是否创建成功,文件已存在或创建失败, 将是否可以继续上传的信息发给客户端 out.write
5.上传文件
1)客户端:
如果可以开始上传文件了
BufferedInputStream包装FileInputStream
BufferedOutputStream包装 socket.getOutputStream()
实现流的对拷,逐个字节拷贝,
2)服务器端
接收客户端上传的数据写入新创建的文件中
BufferedInputStream包装socket.getInputStream()
BufferedOutputStream包装 FileOutputStream
实现流的对拷,逐个字节拷贝。
文件的上传功能小项目
客户端:package com.javami.kudyDemo;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.Socket;public class UploadClient{public static void main(String[] args){Socket socket = null;try{socket = new Socket("127.0.0.1",8888);InputStream ips = socket.getInputStream();OutputStream ops = socket.getOutputStream();//接收欢迎语句Thread.sleep(10);//-->等待线程的写入int len = ips.available();byte[] buf = new byte[len];ips.read(buf);System.out.println(new String(buf));//上传文件名BufferedReader br =new BufferedReader(new InputStreamReader(System.in));System.out.println("请输入你的文件名:");File file = null;while(true){String fileName = br.readLine();if("quit".equals(fileName))return ;file = new File(fileName);if(file.isFile()){ops.write(file.getName().getBytes());break;//如果是文件--写入进去}if(!file.isFile())System.out.println("该文件不存在,请重新输入");elseSystem.out.println("只支持标准文件的上传");}//等待服务端的反馈:buf = new byte[1024];len = ips.read(buf);String info = new String(buf,0,len);System.out.println(info);if(!"可以上传文件".equals(info))return;long fileSize = file.length();ops.write(String.valueOf(fileSize).getBytes());Thread.sleep(100);//上传文件upload(file,ops);//等待服务端的反馈len = ips.read(buf);System.out.println(new String(buf,0,len));}catch(Exception e){e.printStackTrace();}finally{}}private static void upload(File file, OutputStream ops) throws IOException{BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));//读取林的内容BufferedOutputStream bos = new BufferedOutputStream(ops);//写入内容System.out.println("文件上传中~~~~");int ch ;while((ch=bis.read())!=-1){bos.write(ch);}bos.flush();//这个刷新一下就可以.因为让底层去关.要不然就会发生冲突bis.close();//这个必须要关}}服务端:package com.javami.kudyDemo;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;public class UploadServer{/* * 必须要用到多线程去做.如果你没有使用多线程..那么main线程只能和一个连接打交道.. * while * */public static void main(String[]args){ServerSocket ss = null;try{System.out.println("服务器已经开启,正在监听8888端口");ss = new ServerSocket(8888);while(true)//我while循环没有结束-->在监听啦~~~{Socket socket = ss.accept();//当每一个线程都进来的时候,这里会发生阻塞System.out.println("成功与一个客户端建立连接"+socket.getInetAddress().getHostAddress());new Thread(new UploadServers(socket)).start();}} catch (IOException e){// TODO Auto-generated catch blocke.printStackTrace();}finally{if(ss!=null)try{ss.close();} catch (IOException e){// TODO Auto-generated catch blocke.printStackTrace();}}}}客户端的哥们-->package com.javami.kudyDemo;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;public class UploadServers implements Runnable{Socket socket ;public UploadServers(Socket socket){this.socket = socket;}@Overridepublic void run(){try{InputStream ips = socket.getInputStream();OutputStream ops = socket.getOutputStream();ops.write("连接成功,本站支持文件的上传".getBytes());//接收文件名byte[] buf = new byte[1024];int len = ips.read(buf);String fileName = new String(buf,0,len);System.out.println("拿到文件名:"+fileName);//创建文件File file = new File("f:/a",fileName);if(!file.createNewFile()){ops.write("该文件已经存在".getBytes());return;}ops.write("可以上传文件".getBytes());//接收文件的大小len = ips.read(buf);String str = new String(buf,0,len);int fileSize = (int)Integer.parseInt(str);//接收客户端的文件saveFile(ips,file,fileSize);//接收的内容.我的文件名 --> 接收过来的长度//接收从客户端发送过来的文件ops.write("文件上传完毕,恭喜-->使用了".getBytes());} catch (IOException e){// TODO Auto-generated catch blocke.printStackTrace();}}private void saveFile(InputStream ips, File file, int fileSize) throws IOException{BufferedInputStream bis = new BufferedInputStream(ips);//读取内容-->会发生阻塞..BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));int ch;System.out.println("文件上传中,请等下------");for(int i=0; i<fileSize; i++){ch = bis.read();bos.write(ch);}bos.close();//不需要把底层的所关闭~~}}
----------以下内容为自己用文本工具编写..功能实现得比较简单点.以上一样..
客户端:import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.Socket;class MyChlient {/*客户端:文件的上传功能*/public static void main(String[] args) {Socket socket = null;try{socket = new Socket("127.0.0.1",8888);InputStream ips = socket.getInputStream();OutputStream ops = socket.getOutputStream();Thread.sleep(10);byte [] buf = new byte[1024];int len = ips.read(buf);System.out.println(new String(buf,0,len));//发送文件名BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String line ;System.out.println("请输入文件的路径:");File file ;while(true){line = br.readLine();file = new File(line);if(file.isFile()){ops.write(file.getName().getBytes());//把文件的名字发过去break;}if(!file.exists())System.out.println("该目录不存在");elseSystem.out.println("不给力~~~");}//接收客户端反馈信息len = ips.read(buf);String info = new String(buf,0,len);if(!"已经成功创建文件".equals(info))return;System.out.println(info);//上传文件BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));BufferedOutputStream bos = new BufferedOutputStream(ops);int ch;while((ch=bis.read())!=-1){bos.write(ch);}bos.flush();//底层的流我们要刷新一下bis.close();//关闭一下流}catch (Exception e){e.printStackTrace();}finally{try{if(socket!=null)socket.close();}catch (IOException e){e.printStackTrace();}}}}服务端:import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.Socket;import java.net.ServerSocket;class MyServer {public static void main(String[] args) {ServerSocket ss = null;try{ss = new ServerSocket(8888);System.out.println("服务器正在监听8888端口");while(true){Socket socket = ss.accept();System.out.println(socket.getInetAddress().getHostAddress());//获取到连接上来的主机new Thread(new ThreadServer(socket)).start();}}catch (Exception e){e.printStackTrace();}finally{try{if(ss!=null)ss.close();}catch (Exception e){e.printStackTrace();}}}}服务端的多线程实现类import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.BufferedReader;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.Socket;class ThreadServer implements Runnable{Socket socket;public ThreadServer(Socket socket){this.socket = socket;}public void run(){try{InputStream ips = socket.getInputStream();OutputStream ops = socket.getOutputStream();ops.write("欢迎光临本小站,本小站提供文件上传的服务:".getBytes());//接收用户发送的文件名File file;byte[] buf = new byte[1024];int len = ips.read(buf);String fileName = new String(buf,0,len);System.out.println("服务器已经获取到文件名:"+fileName);file = new File("f:/upload",fileName);if(!file.createNewFile()){ops.write("文件已经存在".getBytes());return;}ops.write("已经成功创建文件".getBytes());//接收用户的文件byte [] b = new byte[ips.available()];BufferedOutputStream bos =new BufferedOutputStream(new FileOutputStream(file));//我们把内容写到这边来int ch;while((ch=ips.read())!=-1){bos.write(ch);}bos.close();}catch (Exception e){e.printStackTrace();}finally{try{if(socket!=null)socket.close();}catch (Exception e){e.printStackTrace();}}}}
更为明确的字符反转功能:
客户端:package com.javami.kudyDemo.TCP;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.Socket;public class MySocket{public static void main(String[]args){Socket socket = null;try{socket = new Socket("127.0.0.1",8888);InputStream ips = socket.getInputStream();OutputStream ops = socket.getOutputStream();byte[] buf = new byte[1024];int len = ips.read(buf);String str = new String(buf,0,len);System.out.println(str);BufferedReader br =new BufferedReader(new InputStreamReader(System.in));String line ;System.out.println("请输入你需要转换的数据");while(true){line = br.readLine();if("quit".equals(line))return;ops.write((line).getBytes());Thread.sleep(10);System.out.println("数据反转中......");len = ips.read(buf);System.out.println(new String(buf,0,len));}}catch(Exception e){e.printStackTrace();}finally{if(socket!=null)try{socket.close();} catch (IOException e){// TODO Auto-generated catch blocke.printStackTrace();}}}}服务端:package com.javami.kudyDemo.TCP;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class MyServer{public static void main(String[]args){ServerSocket ss = null;try{ss = new ServerSocket(8888);while(true){Socket socket = ss.accept();//监听成功.服务器返回欢迎的信new Thread(new ThreadSocket(socket)).start();}}catch(Exception e){e.printStackTrace();}finally{}}}他哥们:package com.javami.kudyDemo.TCP;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;public class ThreadSocket implements Runnable{Socket socket ;public ThreadSocket(Socket socket){this.socket = socket;}@Overridepublic void run(){try{InputStream ips = socket.getInputStream();OutputStream ops = socket.getOutputStream();ops.write("提供字母转换:".getBytes());byte[] buf = new byte[1024];int len;while(true){len = ips.read(buf);String str = new String(buf,0,len);if("quit".equals(str))return;StringBuilder sb = new StringBuilder(str);sb = sb.reverse();//反转ops.write(sb.toString().getBytes());}} catch (IOException e){e.printStackTrace();}finally{try{socket.close();}catch(IOException e){e.printStackTrace();}}}}
Dcp的复习:
package com.javami.kudyDemo.TCP;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;public class MyOne{public static void main(String[]args){DatagramSocket dgs = null;DatagramPacket dgp = null;//封包String line = "i live china";byte[] buf = line.getBytes();try{dgs = new DatagramSocket();dgp = new DatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),8888);dgs.send(dgp);//发包} catch (Exception e){// TODO Auto-generated catch blocke.printStackTrace();}finally{if(dgs!=null)dgs.close();}}}package com.javami.kudyDemo.TCP;import java.net.DatagramPacket;import java.net.DatagramSocket;public class MyTwo{public static void main(String[]args){DatagramSocket ds = null;try{ ds = new DatagramSocket(8888); DatagramPacket dp = new DatagramPacket(new byte[1024],1024); ds.receive(dp); byte[] data = dp.getData(); System.out.println(new String(data,0,dp.getLength()));}catch(Exception e){e.printStackTrace();}}}
:
- javase_22(TCP的学习-->)
- T/TCP TCP事物协议的学习
- TCP/IP协议的学习
- TCP协议的学习1
- TCP协议的学习2
- API的学习:TCP&&UDP
- TCP/IP协议的学习
- 我的TCP学习笔记
- Tcp/Ip体系结构的学习
- TCP学习---TCP头
- TCP/IP学习之一(TCP/IP的分层)
- TCP/IP学习之 TCP与UDP的 区别
- TCP/IP详解学习 -- TCP连接的建立与终止
- TCP/IP协议学习(TCP和UDP的区别)
- TCP/IP详解学习笔记--TCP的基本概念
- TCP学习(2)--TCP连接的建立(三次握手)
- TCP学习(3)--TCP释放连接的过程(四次挥手)
- TCP协议的学习(一)TCP服务特点
- Android模拟器中查看app创建的私有文件
- struts2之form标签theme属性详解
- HDOJ 1003 Max Sum
- jQuery性能优化的28个建议
- 学习使用SQLite(版本3.7.4)(中C)
- javase_22(TCP的学习-->)
- 提高hadoop的mapreduce job效率笔记之一(修改mapper和reducer数量)
- HOOK专题
- mini2440(2) LED灯裸机硬件控制程序
- Android中AutoCompleteTextView的使用方法
- JVM学习之:类加载的过程总结
- DM6446相关
- 结构体与类
- error C2276: “&”: 绑定成员函数表达式上的非法操作