TCP Socket:IP地址和端口,套接字
•Socket和ServerSocket •建立客户端和服务器端 •建立连接后,通过Socket中的IO流进行数据的传输 •关闭socket同样,客户端与服务器端是两个独立的应用程序。
TCP传输编程
☆基本思路(客户端)
•客户端需要明确服务器的ip地址以及端口,这样才可以去试着建立连接,如果连接失败,会出现异常。 •连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已经提供了输入流和输出流对象,通过getInputStream(),getOutputStream()获取即可。 •与服务端通讯结束后,关闭Socket。☆基本思路(服务器端)
•服务端需要明确它要处理的数据是从哪个端口进入的。 •当有客户端访问时,要明确是哪个客户端,可通过accept()获取已连接的客户端对象,并通过该对象与客户端通过IO流进行数据传输。 •当该客户端访问结束,关闭该客户端。基于TCP的Socket通信流程
TCP传输编程
☆客户端
通过Socket建立对象并指定要连接的服务端主机以及端口。
<span style="font-family:Times New Roman;font-size:14px;">Socket s = new Socket(“192.168.1.1”,9999); OutputStream out = s.getOutputStream(); out.write(“hello”.getBytes()); s.close(); </span>
☆服务器端
建立服务端需要监听一个端口
<span style="font-family:Times New Roman;font-size:14px;">ServerSocketss = new ServerSocket(9999); Socket s = ss.accept (); InputStream in = s.getInputStream(); byte[] buf = new byte[1024]; intnum = in.read(buf); String str = new String(buf,0,num); System.out.println(s.getInetAddress().toString()+”:”+str); s.close(); ss.close(); </span>
☆思考
对于Web服务器而言,当有多个客户端同时访问服务器时,服务端又如何提供服务呢?
☆TCP传输最容易出现的问题
•客户端连接上服务端,两端都在等待,没有任何数据传输。 •通过例程分析: –因为read方法或者readLine方法是阻塞式。 •解决办法: –自定义结束标记 –使用shutdownInput,shutdownOutput方法。编程练习
☆上传文本文件
读取一个本地文本文件,将数据发送到服务端,服务器端对数据进行存储。存储完毕后,给客户端一个提示。
Client:
<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.net.tcp.uploadTxt; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class UploadTxtClient { public static void main(String[] args) { try { Socket s = new Socket("192.168.2.100",10000); //1上传文本 //源--FileReader BufferedReader br = new BufferedReader( new FileReader("upload/client.txt") ); //目的 socket---OutputStream //BufferedWriter bw = new BufferedWriter( new OutputStreamWriter( s.getOutputStream() )); //建议用打印流 PrintWriter pw = new PrintWriter( s.getOutputStream(), true ); String line = null; while( (line=br.readLine())!=null){ pw.println(line); } //pw.println("over!");//发送自定义的结束标记---有隐患,如果所上传文件中包含该结束标记,就会有问题! //得告诉服务器:上传数据结束 s.shutdownOutput(); //2读取服务器的应答消息 //源socket--s.getInputStream() 字节流 BufferedReader br2 = new BufferedReader( new InputStreamReader( s.getInputStream()) ); //目的显示屏System.out String txt = br2.readLine(); System.out.println("server应答:"+ txt); s.close(); } catch (IOException e) { e.printStackTrace(); } } } </span>Server
<span style="font-family:Times New Roman;font-size:14px;">package cn.hncu.net.tcp.uploadTxt; 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 UploadTxtServer { public static void main(String[] args) { try { ServerSocket ser = new ServerSocket(10000); while(true){ Socket s = ser.accept(); //接收上传的文件 //源 socket--字节流 -->字符流 且 带缓存 BufferedReader br = new BufferedReader( new InputStreamReader(s.getInputStream())); //目的 FileWriter PrintWriter pw = new PrintWriter( new FileWriter("upload/server.txt"),true); String line = null; while( (line=br.readLine())!=null ){ // if("over!".equals(line)){ // break; // } pw.println(line); } //发送应答消息 PrintWriter pw2 = new PrintWriter(s.getOutputStream(),true); pw2.println("上传成功"); s.close(); } } catch (IOException e) { e.printStackTrace(); } } } </span>☆上传图片文件
客户端需求:把一个图片文件发送到服务端并读取回馈信息。要求判断文件是否存在及格式是否为jpg或gif并要求文件小于2M。
服务端需求:接收客户端发送过来的图片数据。进行存储后,回馈一个上传成功字样。支持多用户的并发访问。
Client:
<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.net.tcp.uploadPic; 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; import javax.swing.JFileChooser; import javax.swing.JOptionPane; public class UploadPicClient { public static void main(String[] args) { JFileChooser jfc = new JFileChooser(); int res = jfc.showOpenDialog(null); if(res!=JFileChooser.APPROVE_OPTION ){ return; } File file = jfc.getSelectedFile(); if(!file.exists()){ JOptionPane.showMessageDialog(null, "该文件不存在"); return; } //dsj.gif.ext a.jpg.txt aa.txt.jpg if(!(file.getName().endsWith(".jpg") || file.getName().endsWith(".gif"))){ JOptionPane.showMessageDialog(null, "只允许上传jpg或gif格式!"); return; } if(file.length()>=1024*1024*2){//大于2M JOptionPane.showMessageDialog(null, "文件大小不能超过2M!"); return; } //经过上面的防护,要上传的文件对象file是合法的 try { Socket s = new Socket("127.0.0.1",10001); //源: file--字节流 FileInputStream FileInputStream fin = new FileInputStream(file); //目的: socket--outputStream 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[512]; int len2 = in.read(buf2); System.out.println( new String(buf2,0,len2)); //关流 in.close(); fin.close(); out.close(); s.close(); } catch (IOException e) { e.printStackTrace(); } } } </span>Server:
<span style="font-family:Times New Roman;font-size:14px;color:#000000;">package cn.hncu.net.tcp.uploadPic; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class UploadPicServer { public static void main(String[] args) { try { ServerSocket ser = new ServerSocket(10001); while(true){ Socket s = ser.accept(); new Thread( new UploadThread(s) ).start(); } } catch (IOException e) { e.printStackTrace(); } } } class UploadThread implements Runnable{ private Socket s = null; public UploadThread( Socket s){ this.s = s; } @Override public void run() { String ip = s.getInetAddress().getHostAddress(); System.out.println(ip+".......connected..."); try { File dir = new File("pics"); if(!dir.exists()){ dir.mkdir(); } File file = new File(dir,ip+".jpg"); int count=1; while(file.exists()){ file = new File(dir,ip+"("+ (count++) +").jpg"); } InputStream in = s.getInputStream(); FileOutputStream fout = new FileOutputStream(file); byte buf[] = new byte[512]; int len=0; while( (len=in.read(buf))!=-1){ fout.write(buf, 0, len); } //给客户端应答消息 s.getOutputStream().write( "上传成功".getBytes() ); fout.close(); s.close(); } catch (IOException e) { e.printStackTrace(); } } } </span>