标签:
TCP传输
TCP Socket:IP地址和端口,套接字
Socket和ServerSocket
建立客户端和服务器端
建立连接后,通过Socket中的IO流进行数据的传输
关闭socket
同样,客户端与服务器端是两个独立的应用程序。
TCP传输编程
☆基本思路(客户端)
客户端需要明确服务器的ip地址以及端口,这样才可以去试着建立连接,如果连接失败,会出现异常。
连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已经提供了输入流和输出流对象,通过getInputStream(), getOutputStream()获取即可。
与服务端通讯结束后,关闭Socket。
☆基本思路(服务器端)
服务端需要明确它要处理的数据是从哪个端口进入的。
当有客户端访问时,要明确是哪个客户端,可通过accept()获取已连接的客户端对象,并通过该对象与客户端通过IO流进行数据传输。
当该客户端访问结束,关闭该客户端。
基于TCP的Socket通信流程
TCP传输编程
☆客户端
通过Socket建立对象并指定要连接的服务端主机以及端口。
Socket s = new Socket(“192.168.1.1”,9999); OutputStream out = s.getOutputStream(); out.write(“hello”.getBytes()); s.close();☆服务器端
建立服务端需要监听一个端口
ServerSocket ss = new ServerSocket(9999); Socket s = ss.accept (); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; int num = in.read(buf); String str = new String(buf,0,num); System.out.println(s.getInetAddress().toString()+”:”+str); s.close(); ss.close();
具体实例:
客户端:
package cn.hncu.tcp; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; public class MyClientSocket { public static void main(String[] args) { try { Socket s = new Socket("192.168.31.168",8888);//和服务器进行三次握手,若失败则出异常,否则返回和对方通讯的socket //发送数据 OutputStream out = s.getOutputStream(); out.write( "Hello Server!".getBytes() ); //接收服务器的应答数据 InputStream in = s.getInputStream(); DataInputStream din = new DataInputStream(in); System.out.println( din.readUTF() ); s.close(); din.close(); } catch (IOException e) { e.printStackTrace(); } } }服务器端:
package cn.hncu.tcp; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class MyServerSocket { public static void main(String[] args) { try { ServerSocket server = new ServerSocket(8888); while(true){ System.out.println("准备接收一个连接...."); Socket s = server.accept();//阻塞式方法 System.out.println("收到一个连接...."); //读--从客户端读数据 InputStream in = s.getInputStream(); byte buf[] = new byte[20]; in.read(buf); System.out.println("read info:"+ new String(buf) ); //写--应答客户端--向他写数据 OutputStream out = s.getOutputStream(); DataOutputStream dout = new DataOutputStream(out); dout.writeUTF("Hello,"+s.getInetAddress()+"port#"+s.getPort()+"\nbye!"); dout.close(); s.close(); } } catch (IOException e) { e.printStackTrace(); } } }
编程练习
1、上传文本文件(本例只考虑只有一个客户端)
读取一个本地文本文件,将数据发送到服务端,服务器端对数据进行存储。 存储完毕后,给客户端一个提示。
客户端:
package cn.hncu.tcp.upload; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; import java.net.UnknownHostException; public class UploadTextClient { public static void main(String[] args) { try { Socket s = new Socket("192.168.1.106",10005); //思路:把本地文件的数据读取出来通过 s.getOutputStream()获得的out对象发送出去 BufferedReader br = new BufferedReader(new FileReader("tempfiles\\client.txt")); OutputStream out = s.getOutputStream();//这里的输出流 对应的是服务器端的输入流 PrintWriter pw = new PrintWriter(out, true);//建议不要用BufferedWriter String line = null; while( (line=br.readLine())!=null){ pw.println(line); } //给服务器发送结束标记---上传结束,要加结束标记,否则服务器在数据接收完毕时再调用read()或readLine()时会出异常 //法1:pw.println("over#$@#@$");//不能出现文件中存在的结束关键字---搞特殊一点 //法2---建议采用该种方式---由socket内部来指定结束标记 s.shutdownOutput(); br.close(); //读取服务器上传成功的反馈消息 BufferedReader br2 = new BufferedReader(new InputStreamReader(s.getInputStream())); String info = br2.readLine(); System.out.println("server应答:"+info); s.close(); br2.close(); }catch (IOException e) { e.printStackTrace(); } } }服务器端:
package cn.hncu.tcp.upload; import java.io.BufferedReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class UploadTextServer { public static void main(String[] args) { try { ServerSocket server = new ServerSocket(10005); Socket s = server.accept(); System.out.println(s.getInetAddress().getHostAddress()+"...connected"); //读取客户端上传过来的文本文件 //源 ---socket(字节流)---额外:需要转换成字符流 ,缓存流 BufferedReader br = new BufferedReader( new InputStreamReader(s.getInputStream())); //目的 ---硬盘字符流 FileWriter---额外:打印流 PrintWriter pw = new PrintWriter(new FileWriter("tempfiles\\server.txt"), true); String line=null; while ( (line=br.readLine())!=null ){ // if("over#$@#@$".equals(line)){ // break; // } pw.println(line); } pw.close(); //上传成功,给客户端一个提示信息 PrintWriter pw2 = new PrintWriter(s.getOutputStream(),true); pw2.println("上传成功!"); s.close(); server.close(); pw2.close(); } catch (IOException e) { e.printStackTrace(); } } }
客户端:
package cn.hncu.tcp.upload; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; public class UploadPicClient { public static void main(String[] args) { //卫条件 if(args.length!=1){ System.out.println("请指定文件"); return; } File file = new File(args[0]); if(!(file.exists() && file.isFile()) ){ System.out.println("上传的文件不存在"); return; } if( !(file.getName().endsWith(".jpg")||file.getName().endsWith(".gif")) ){ System.out.println("文件扩展名必须是jpg或gif"); return; } if( file.length()>=1024*1024*2){ System.out.println("文件过大,不应超过2M,请重新上传!"); return; } //上传 try { Socket s = new Socket("127.0.0.1",9999); FileInputStream fin = new FileInputStream(file); OutputStream out = s.getOutputStream(); byte buf[] = new byte[1024]; int len=0; while( (len=fin.read(buf))!=-1){ out.write(buf, 0, len); } s.shutdownOutput();//告诉服务器,文件上传完毕 //读取服务器的回馈信息 InputStream in = s.getInputStream(); byte buf2[] = new byte[1024]; int len2 = in.read(buf2); String info = new String(buf2,0,len2); System.out.println(info); //关流 fin.close(); s.close(); } catch (IOException e) { e.printStackTrace(); } } }服务器端:
package cn.hncu.tcp.upload; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class UploadPicServer { public static void main(String[] args) { try { ServerSocket server = new ServerSocket(9999); while(true){ Socket s = server.accept();//只负责和客户端进行握手 new Thread( new UploadThread(s)).start(); } //server.close(); } catch (IOException e) { e.printStackTrace(); } } } class UploadThread implements Runnable{ private Socket s; public UploadThread(Socket s) { this.s = s; } @Override public void run() { String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+"...connected"); try { InputStream in = s.getInputStream(); File dir = new File("d:\\mypic"); if(!dir.exists()){ dir.mkdir(); } int count=1; File file = new File(dir,ip+".jpg"); while(file.exists()){ file = new File(dir,ip+"("+(count++) +")"+".jpg"); //带号的文件名 } FileOutputStream fout = new FileOutputStream(file); //从socket流中读取数据,存储到本地文件。相当于对拷 byte buf[] = new byte[1024]; int len=0; while( (len=in.read(buf))!=-1){ fout.write(buf, 0, len); } //图片接收完毕 //向客户端发送回馈信息 OutputStream out = s.getOutputStream(); out.write( "上传成功".getBytes() ); fout.close(); s.close(); } catch (IOException e) { e.printStackTrace(); } } }
标签:
原文地址:http://blog.csdn.net/x121850182/article/details/51362205