zoukankan      html  css  js  c++  java
  • 63 网络编程(四)——TCP编程

    TCP编程

    TCP编程是面向连接的数据传输,所以需要时用IO流来建立连接。

    用户输出流到服务器,服务器输入流接收数据。

    服务器输出流到用户,用户输入流接收。

    基本流程

    服务器端

    • 创建服务器端:ServerScoekt 对象
    • 阻塞时监听用户接入:accep() 返回Socket对象
    • 建立连接:与返回的Socket对象建立IO流,getInputStream()方法与getOutputStream方法
    • 处理数据
    • 关闭流,关闭Socket对象,关闭服务器(一般不关服务器)

    用户端

    • 创建Socket对象:Socket(targetHost,targetPort)
    • 建立连接:创建输出流
    • 传输数据:输入流写
    • 关闭流
    • 关闭Socket对象

    基础版本示例

    服务器端

    package _20191218;
    
    import java.io.DataInputStream;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     * 通过tcp传输数据的服务端,实现的是服务器端
     * @author TEDU
     *
     */
    public class TCPServer {
    	public static void main(String[] args) throws IOException {
    		System.out.println("-----server------");
    		//建立服务器
    		ServerSocket server = new ServerSocket(6677);
    		//阻塞式接收Socket
    		Socket client = server.accept();
    		//建立连接
    		DataInputStream dis = new DataInputStream(client.getInputStream());//选择需要的合适的流,不需要如本文的流
    		//接收数据并处理
    		Object obj1 = dis.readUTF();
    		Object obj2 = dis.readInt();
    		Object obj3 = dis.readFloat();
    		System.out.println(obj1);
    		System.out.println(obj2);
    		System.out.println(obj3);
    		//关闭流及服务器
    		dis.close();
    		client.close();
    		//server.close()//服务器无需关闭
    	}
    }
    

      

    用户端

    package _20191218;
    
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    public class TCPClient {
    	public static void main(String[] args) throws UnknownHostException, IOException {
    		System.out.println("-----client------");
    		//新建客户端Socket
    		Socket client = new Socket("localhost",6677);
    		//建立连接
    		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
    		//发送数据
    		String str = "fuck";
    		dos.writeUTF(str);
    		dos.writeInt(89);
    		dos.writeFloat(213.4f);
    		//关闭流和连接
    		dos.close();
    		client.close();
    	}
    }
    

      

    测试结果

    模拟登陆服务器

    客户端与服务器端都可以想对方发送消息。但服务器方是被动响应消息。

    服务器端

    package _20191218;
    
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     * 服务器有响应功能,对于用户的请求进行处理,如账号密码均正确,回应登录成功,否则回应登录失败
     * @author TEDU
     *
     */
    public class TCPLoginServer {
    	public static void main(String[] args) throws IOException {
    		System.out.println("服务器端开启");
    		//创建服务器端
    		ServerSocket server = new ServerSocket(6677);//端口号不能忘
    		//阻塞式监听请求:Socket accept()
    		Socket client = server.accept();
    		//建立连接
    		DataInputStream dis = new DataInputStream(client.getInputStream());
    		//读取数据
    		String str = dis.readUTF();
    		String[] datas = str.split("&");
    		int count = 0;
    		//输出IO流
    		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
    		for(String data : datas) {
    			if(data.equals("zhanghao")) {
    				count++;
    			}
    			if(data.equals("mima")){
    				count++;
    			}
    		}
    		if(count == 2) {
    			dos.writeUTF("登陆成功");
    		}else {
    			dos.writeUTF("登录失败");
    		}
    		//关闭流、关闭服务器(如果有必要的话)
    		dos.close();
    		dis.close();
    		//server.close();//关闭服务器,如果必要的话
    	}
    }
    

      

    客户端

    package _20191218;
    
    import java.io.BufferedOutputStream;
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.ByteArrayOutputStream;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.util.Scanner;
    
    /**
     * 客户端请求,输入账号密码试图登录服务器
     * @author TEDU
     *
     */
    public class TCPLoginClient {
    	public static void main(String[] args) throws UnknownHostException, IOException {
    		System.out.println("用户端开启");
    		//创建用户端
    		Socket client  = new Socket("localhost",6677);
    		System.out.println(client);
    		//建立连接
    		DataOutputStream dos = new DataOutputStream(client.getOutputStream());
    		//用户输入账号密码
    		Scanner scan = new Scanner(System.in);
    		System.out.println("请输入账号:");
    		String account = scan.nextLine();
    		System.out.println("请输入密码:");
    		String password = scan.nextLine();
    		//传输数据
    		dos.writeUTF(account+"&"+password);
    //		bw.write(password);
    		dos.flush();
    		//等待响应
    		DataInputStream dis = new DataInputStream(client.getInputStream());
    		System.out.println(dis.readUTF());
    		//关闭连接(如果需要的话)
    		dis.close();
    		dos.close();
    		client.close();
    	}
    }
    

      

    测试结果

    文件传输至服务器

    客户端将文件传输至服务器端。

    客户端

    package _20191218;
    
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.Socket;
    
    /**
     * 从客户端传动文件到服务器端
     * @author TEDU
     *
     */
    public class FileTCPClient {
    	public static void main(String[] args) throws IOException {
    		//创建客户端
    		Socket client = new Socket("localhost",6687);
    		//与本地文件建立连接 IO流
    		InputStream is = new FileInputStream(new File("GIF.gif"));
    		//与客户端建立连接 IO流
    		OutputStream os = new BufferedOutputStream(client.getOutputStream());
    		//读取并发送文件
    		byte[] datas = new byte[1024*10];
    		int len;
    		while((len = is.read(datas))!=-1) {//读取文件
    			os.write(datas,0,len);//发送文件
    		}
    		os.flush();
    		//关闭流及端
    		os.close();
    		is.close();
    		client.close();
    	}
    }
    

      

    服务器端

    package _20191218;
    
    import java.io.BufferedInputStream;
    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;
    
    /**
     * 接收并存储从客户端传过来的文件
     * @author TEDU
     *
     */
    public class FileTCPServer {
    	public static void main(String[] args) throws IOException {
    		//建立服务器端
    		ServerSocket server = new ServerSocket(6687);
    		//阻塞式接收Socket
    		Socket client = server.accept();
    		//与客户端建立连接
    		InputStream is = new BufferedInputStream(client.getInputStream());
    		//与本地文件建立连接(如文件为空则新建)
    		OutputStream os = new FileOutputStream(new File("copy.gif"));
    		//读取数据
    		byte[] datas = new byte[1024*10];
    		int len;
    		while((len = is.read(datas))!=-1) {
    			//处理数据:写入文件
    			os.write(datas,0,len);
    		}
    		os.flush();
    		//关闭流与连接
    		os.close();
    		is.close();
    		server.close();
    	}
    }
    

      

    先运行服务器端,再运行客户端即可复制完成。

    模拟多人登录服务器:服务器多线程

    运行一个服务器端,运行多个用户端尝试登录。多开几个控制台。

    服务器端

    package _20191218;
    
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /**
     * 支持多用户登录的服务器
     * @author TEDU
     */
    public class TCPMultipleLoginServer{
    	public static void main(String[] args) {
    		System.out.println("服务器开启");
    		//新建服务器端
    		ServerSocket server = null;
    		try {
    			server = new ServerSocket(6788);
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		//声明客户端套机字
    		Socket client = null;
    		//循环运行请求服务器
    		while(true) {
    			//客户端套接字
    			try {
    				client = server.accept();//阻塞接受请求
    				System.out.println("有用户尝试登录");
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			//线程开始(接受客户端发来的数据,做出回应)
    			new Thread(new Channel(client)).start();
    		}
    		
    	}
    	//写一个内部类,用来实现Runnable接口
    	static class Channel implements Runnable{
    		//输入流与输出流
    		DataInputStream dis;
    		DataOutputStream dos;
    		//构造方法:传入已经创建好的client
    		public Channel(Socket client) {
    			//建立连接
    			try {
    				dis  = new DataInputStream(client.getInputStream());
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			try {
    				dos = new DataOutputStream(client.getOutputStream());
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    		public void run() {
    			//接受数据
    			String[] datas = Receive();
    			//响应
    			if(datas[0].equals("zhanghao")&&datas[1].equals("mima")) {
    				send("登陆成功");
    			}else {
    				send("登录失败");
    			}
    			//关闭
    			release();
    		}
    		//接受请求数据
    		public String[] Receive() {
    			try {
    				String[] datas = dis.readUTF().split("&");
    				return datas;
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			return null;
    		}
    		//响应
    		public void send(String response) {
    			try {
    				dos.writeUTF(response);
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    		//关闭
    		public void release() {
    			try {
    				dos.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			try {
    				dis.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

      

    用户端

      

    package _20191218;
    
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.util.Scanner;
    
    /**
     * TCP多用户登录服务器
     */
    public class TCPMultipleLoginClient{
    	public static void main(String[] args) {
    		//创建客户端套接字
    		Socket client = null;
    		try {
    			client = new Socket("localhost",6788);
    		} catch (UnknownHostException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		new Send(client).send();
    		new Receive(client).receive();
    	}
    	//创建传输数据类
    	static class Send{
    		//输出流
    		DataOutputStream dos;
    		//构造方法:传入client
    		public Send(Socket client) {
    			try {
    				dos = new DataOutputStream(client.getOutputStream());
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    		//传输数据到服务器的方法
    		public void send() {
    			Scanner scan = new Scanner(System.in);
    			System.out.println("请输入账号:");
    			String account = scan.nextLine();
    			System.out.println("请输入密码:");
    			String password = scan.nextLine();
    			try {
    				dos.writeUTF(account+"&"+password);
    				dos.flush();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    	//创建接收数据类
    	static class Receive{
    		//输入流
    		DataInputStream dis;
    		public Receive(Socket client) {
    			try {
    				dis = new DataInputStream(client.getInputStream());
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    		//接收方法
    		public void receive() {
    			try {
    				String message = dis.readUTF();
    				System.out.println(message);
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }
    

      

  • 相关阅读:
    [蓝桥杯] 第39级台阶
    [蓝桥杯] 马虎的算式
    POJ 1142 Smith Numbers(史密斯数)
    HDU 1181 变形课
    HDU 1728 逃离迷宫
    HDU 2188 悼念512汶川大地震遇难同胞――选拔志愿者 巴什博奕
    HDU 2177 取(2堆)石子游戏 (威佐夫博弈)
    HDU 1847 Good Luck in CET-4 Everybody! 博弈
    HDU 1525 Euclid's Game
    HDU 1517 A Multiplication Game 博弈
  • 原文地址:https://www.cnblogs.com/Scorpicat/p/12059021.html
Copyright © 2011-2022 走看看