网络编程(三)--TCP

来源:互联网 发布:js 跳转url 隐藏参数 编辑:程序博客网 时间:2024/05/16 08:13

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;}@Overridepublic void run() {String ip = s.getInetAddress().getHostAddress(); //获取对方IPSystem.out.println(ip + "connected.....");// 接收文件上传 :流拷贝// 1源 :socket InputStraemtry {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目的 FileInputStreambos = 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// 目的: 磁盘 ---> FileWriterbr = 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 --> OutputStreambr = 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("文件流关闭失败!");}}}}}







原创粉丝点击