基于TCP实现用户数据数据传输案例

TCP Socket:IP地址和端口,套接字

1)Socket和ServerSocket
2)建立客户端和服务器端
3)建立连接后,通过Socket中的IO流进行数据的传输
4)关闭socket         
同样,客户端与服务器端是两个独立的应用程序。

☆基本思路(客户端)

1)客户端需要明确服务器的ip地址以及端口,这样才可以去试着建立连接,如果连接失败,会出现异常。
2)连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已经提供了输入流和输出流对象,通过getInputStream(), getOutputStream()获取即可。
3)与服务端通讯结束后,关闭Socket。

☆基本思路(服务器端)

1)服务端需要明确它要处理的数据是从哪个端口进入的。
2)当有客户端访问时,要明确是哪个客户端,可通过accept()获取已连接的客户端对象,并通过该对象与客户端通过IO流进行数据传输。
3)当该客户端访问结束,关闭该客户端。

☆客户端

通过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();


☆TCP传输最容易出现的问题
1)客户端连接上服务端,两端都在等待,没有任何数据传输。
a通过例程分析:
  1)因为read方法或者readLine方法是阻塞式。
b解决办法:
  1)自定义结束标记
  2)使用shutdownInput,shutdownOutput方法。

实战项目:

☆上传图片文件

客户端需求:把一个图片文件发送到服务端并读取回馈信息。要求判断文件是否存在及格式是否为jpg或gif并要求文件小于2M。
服务端需求:接收客户端发送过来的图片数据。进行存储后,回馈一个 上传成功字样。支持多用户的并发访问。

服务器端:

package cn.hucu.TCP.uploadPicFile;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class uploadPicFileServer {
	// main线程只负责握手
	public static void main(String[] args) throws IOException {
		ServerSocket server = new ServerSocket(10006);
		while (true) {
			Socket s = server.accept();
			new Thread(new UploadThread(s)).start();
		}
	}
}
class UploadThread implements Runnable {
	private Socket s;  
	private BufferedInputStream bis; //用户信息对象
	private BufferedOutputStream bos; 
	private OutputStream out; // 反馈给用户的流对象
	public UploadThread(Socket s) {
		this.s = s;
	}
	@Override
	public void run() {
		String ip = s.getInetAddress().getHostAddress(); //获取对方IP
		System.out.println(ip + "connected.....");
		// 接收文件上传 :流拷贝
		// 1源 :socket InputStraem
		try {
			bis = new BufferedInputStream(s.getInputStream());
			// 服务器端文件名的取法:ip.jpg,ip(1).jpg,ip(2).jpg,ip(3).jpg.....
			File dir = new File("upload/pics");
			/**
			 * 判断文件是否存在,如果没有,则创建一个文件
			 */
			if (!dir.exists()) {
				dir.mkdir(); 
			}
			int count = 1;
			File file = new File(dir, ip + ".jpg");
			if (file.exists()) {
				file = new File(dir, ip + "(" + (count++) + ")" + ".jpg");
			}
			// 经过前面的防护,此时的file
			// 2目的 FileInputStream
			bos = new BufferedOutputStream(new FileOutputStream(file));
			// 3while对拷
			byte buf[] = new byte[1024];
			int len = 0;
			while ((len = bis.read(buf)) != -1) {
				bos.write(buf, 0, len);
			}
			/**
			 *  给客户端反馈提示信息
			 */
			OutputStream out = s.getOutputStream();
			out.write("图片上传成功!".getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					throw new RuntimeException("关流失败!!");
				}
			}
			if (bos != null) {
				try {
					bos.close();
				} catch (IOException e) {
					throw new RuntimeException("关流失败!!");
				}
			}
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					throw new RuntimeException("关流失败!!");
				}
			}
			try {
				s.close();
			} catch (IOException e) {
				throw new RuntimeException("关流失败!!");
			}
		}
	}
}


客服端:

package cn.hucu.TCP.uploadPicFile;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

public class uploadPicFileClient {
	public static void main(String[] args)  {
		try {
			//让用户选择图片并进行格式校验
			JFileChooser jfc = new JFileChooser();
			int res = jfc.showOpenDialog(null);
			if(res!=JFileChooser.APPROVE_OPTION){
				return ;
			}
			File file = jfc.getSelectedFile();
			
			if(file.length()>1024*1024*2){
				JOptionPane.showMessageDialog(null, "文件太大,不能超过2M!");
				return;
			}
			if(!(file.getName().endsWith(".jpg")||file.getName().endsWith(".jpg"))){
				JOptionPane.showMessageDialog(null, "文件格式错误,要求必须是jpg或gif!");
				return;
			}			
			Socket s =new Socket("127.0.0.1",10006);
			//流拷贝:  FileXXX --> Socket
			//1源
			BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
			//2目的
			BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
			//3while()拷贝
			byte buf[] = new byte[1024];
			int len=0;
			while( (len=bis.read(buf))!=-1 ){
				bos.write(buf, 0, len);
			}
			bos.flush();//bug:虽然是字节流,但因为是缓存流(里面带缓存),所以要手动刷缓存
			//告诉服务器,图片文件上传完毕
			s.shutdownOutput();//Socket里面判断文件结束的标记			
			//接受服务器的反馈信息
			InputStream in = s.getInputStream();
			byte bs[] = new byte[1024];
			int len2 = in.read(bs);
			String info = new String(bs,0,len2);			
			System.out.println("服务器应答:"+info);
			//关流
			bis.close();
			bos.close();
			in.close();
			s.close();
		} catch (IOException e) {
			throw new RuntimeException("文件失败!");
		}
		
	}
}

项目实战(二):

☆上传文本文件:读取一个本地文本文件,将数据发送到服务端,服务器端对数据进行存储。 存储完毕后,给客户端一个提示。

服务器端:

package cn.hucu.TCP.uploadTxetFile;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JOptionPane;

public class uploadTextFileServer {
	public static void main(String[] args) {
		ServerSocket server = null;
		Socket s = null;
		BufferedReader br = null;
		PrintWriter pw = null;
		PrintWriter out = null;
		try {
			server = new ServerSocket(10005);
			s = server.accept();
			// 1 接收客户端上传的文件并存储到磁盘
			// 源: Socket---> s.getInputStream --InputStream
			// 目的: 磁盘 ---> FileWriter
			br = new BufferedReader(new InputStreamReader(s.getInputStream()));
			pw = new PrintWriter(new FileWriter("upload/server.txt"));
			String str = "";
			while ((str = br.readLine()) != null) {
				if ("$^^%^&".equals(str)) { // 自定义结束标记
					break;
				}
				pw.println(str);
			}
			// 回馈给用户发送成功
			out = new PrintWriter(s.getOutputStream(), true);// 自动刷缓冲
			out.write("上传成功!!!");

		} catch (IOException e) {
			JOptionPane.showMessageDialog(null, "文件上传失败!!");
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					throw new RuntimeException("缓冲流关闭失败!!!");
				}
			}
			if (pw != null) {
				pw.close();
			}
			if (out != null) {
				out.close();
			}
			if (s != null) {
				try {
					s.close();
				} catch (IOException e) {
					throw new RuntimeException("Socket流关闭失败!!!");
				}
			}
		}
	}
}

客户端:

package cn.hucu.TCP.uploadTxetFile;

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 uploadTextFileClient {
	public static void main(String[] args) {
		Socket s = null;
		BufferedReader br = null;
		BufferedReader br2 = null;
		PrintWriter pw = null;
		try {
			s = new Socket("127.0.0.1", 10005);
			// 1上传文件
			// 源: 磁盘文件 ---FileReader
			// 目的:socket ---s.getOutputStream --> OutputStream
			br = new BufferedReader(new FileReader("upload/blog.txt"));
			pw = new PrintWriter(s.getOutputStream(), true);
			String str = "";
			while ((str = br.readLine()) != null) {
				pw.println(str);
			}
			// pw.println("$^^%^&");自定义结束标记
			s.shutdownOutput();

			// 2接收服务器的反馈信息(上传成功的提示)
			br2 = new BufferedReader(new InputStreamReader(s.getInputStream()));
			String str2 = null;
			while ((str2 = br2.readLine()) != null) { // 如果回馈信息较大,
				System.out.println(str2);
			}

		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (s != null) {
				try {
					s.close();
				} catch (IOException e) {
					throw new RuntimeException("Socket流关闭失败!");
				}
			}
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					throw new RuntimeException("打印流关闭失败!");
				}
			}
			if (br2 != null) {
				try {
					br2.close();
				} catch (IOException e) {
					throw new RuntimeException("打印流关闭失败!");
				}
			} 
			if (pw != null) {
				try {
					pw.close();
				} catch (Exception e) {
					throw new RuntimeException("文件流关闭失败!");
				}
			}

		}
	}
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值