之前因为学校的java课程设计做了一个很简单的聊天室,现在想起来真的想吐。
网络编程之socket编程是挺简单的,但是底层的东西总是不能理解,后来我才知道,一直使用java使我变得不关心底层,总是期待某些类的某些方法在API文档上。于是乎,底层关我屁事,我只需要做出来就行了,这玩意就是这个样子的。
感觉这玩意很神奇,你看那个YY直播和斗鱼TV,那些肯定是靠流来实现的。 类似于QQ,你看这玩意可以聊天,虽然是基于socket和多线程,但是我还是觉得,QQ内部规定的协议规定得多少啊。 还是别想了,就好像原始人在构思机器人一样。 水平不够。。。。
UDP: 1 每个数据报中都给出了完整的地址信息,因此无需要建立发送方和接收方的连接。
2 UDP传输数据时是有大小限制的,每个被传输的数据报必须限定在64KB之内。
3 UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方
TCP: 1 面向连接的协议,在socket之间进行数据传输之前必然要建立连接,所以在TCP中需要连接时间。
2 TCP传输数据大小限制,一旦连接建立起来,双方的socket就可以按统一的格式传输大的数据。
3 TCP是一个可靠的协议,它确保接收方完全正确地获取发送方所发送的全部数据。
/** * 客户端代码 * @author suibian * */ public class Client { public static void main(String[] args) throws Exception { Socket s=new Socket("localhost",10000); //创建一个socket对象 Scanner sc=new Scanner(System.in); InputStreamReader isr=new InputStreamReader(s.getInputStream()); //获取输入流 BufferedReader br=new BufferedReader(isr); //当然有其他的方式 OutputStream oos=s.getOutputStream(); //获取输出流 PrintWriter out=new PrintWriter(oos); System.out.println("Write to Server :"); String words=sc.nextLine(); while(!words.equals("bye")){ //如果输入不是bye的话,那么发送到服务器中去 out.println(words); out.flush(); //一定要记得刷新一下流,否则服务器收不到数据 String response=br.readLine(); //获取服务器返回的数据 System.out.println("Server response:"+response); words=sc.nextLine(); } s.close(); //最后记得要关闭 } }
/** * 服务器端代码 * @author suibian * */ public class Server { public static void main(String[] args) throws IOException { ServerSocket socket=new ServerSocket(10000); //监听本机端口为10000 System.out.println("Server start! "+socket.getInetAddress()); Scanner sc=new Scanner(System.in); while(true){ Socket s=socket.accept(); System.out.println("One client connectioned"); NetClient client=new NetClient(s); //放到一个线程中去处理好 new Thread(client).start(); } } static class NetClient implements Runnable{ private Socket s; /*是一个包装类,它可以包装字符流,将字符流放入缓存里,先把字符读到缓存里,到缓存满了或者你flush的时候,再读入内存,就是为了提供读的效率而设计的。*/ private BufferedReader reader; /*PrintWriter是 打印流是向文件输 的首选的类 ,不用关注他输入的是不是中文 ,这个类已经给我们处理好了,不会出现中文乱码*/ private PrintWriter out; private Scanner scanner=new Scanner(System.in); public NetClient(Socket s) throws IOException { this.s = s; InputStreamReader isr=new InputStreamReader(s.getInputStream()); reader=new BufferedReader(isr); OutputStream oos=s.getOutputStream(); out=new PrintWriter(oos); } public void run() { try { String clientWords = reader.readLine(); //从客户端读到的数据 System.out.println("Clent:"+s.getRemoteSocketAddress()+" to server:"+clientWords); System.out.println("Write what u want to say?"); String response=scanner.nextLine(); //服务器返回给客户端的数据 while(!response.equals("bye")){ out.println(response); out.flush(); clientWords=reader.readLine(); System.out.println("Clent:"+s.getRemoteSocketAddress()+"to server:"+clientWords); if(clientWords.equals("bye")){ System.out.println("Clent "+s.getRemoteSocketAddress()+" disconnection"); break; } System.out.println("Write what u want to say?"); response=scanner.nextLine(); } out.close(); reader.close(); s.close(); } catch (IOException e) { e.printStackTrace(); } } } }
需求:设计一个简单的银行访问协议,如下 : 客户机请求 服务齐全响应 意义 BALANCE n n 余额 客户机将获得账户n的余额 DEPOSIT n a n 余额 将数量为a的款项存入账户n WITHDRAW n a n 余额 从账户支出数量为a的款项 QUIT 无响应 退出连接 |
public class Account { private double balance; public Account(){ balance=0; } public Account(double initialBalance){ balance=initialBalance; } /** * 返回账户余额 */ public double getBalance() { return balance; } /** *存钱 */ public void deposit(double amount){ balance+=amount; } /** * 取钱 */ public void withdraw(double amount){ balance-=amount; } }
/** * 银行类 * @author suibian * */ public class Bank { private List<Account> accounts; public Bank(int initalSize){ accounts=new ArrayList<Account>(); for(int i=0;i<initalSize;i++){ accounts.add(new Account()); } } /** * 存钱的业务 */ public void deposit(int accountId,double amount){ accounts.get(accountId-1).deposit(amount); } /** * 取钱业务 */ public void withdraw(int accountId,double amount){ accounts.get(accountId-1).withdraw(amount); } /** * 获取余额 */ public double getBalance(int accountId){ return accounts.get(accountId-1).getBalance(); } }
/** * 客户端代码 * @author suibian * */ public class ATMClient { public static void main(String[] args) throws UnknownHostException, IOException { Socket socket=new Socket("localhost",8888); InputStream stream=socket.getInputStream(); OutputStream output=socket.getOutputStream(); System.out.println("Connected Server"+socket.toString()); Scanner in=new Scanner(stream); PrintWriter out=new PrintWriter(output); /*客户机将获得账户n的余额 */ String command="BALANCE 3\n"; out.print(command); out.flush(); String response=in.nextLine(); System.out.println("result is:"+response); System.out.println("================================================"); /*将数量为a的款项存入账户n*/ command="DEPOSIT 3 1000\n"; System.out.println("Client send request:"+command); out.print(command); out.flush(); response=in.nextLine(); System.out.println("result is:"+response); System.out.println("================================================"); /*从账户支出数量为a的款项*/ command="WITHDRAW 3 500\n"; System.out.println("Client send request:"+command); out.print(command); out.flush(); response=in.nextLine(); System.out.println("result is:"+response); System.out.println("================================================"); /*退出连接*/ command="QUIT\n"; System.out.println("Client send request:"+command); out.print(command); out.flush(); response=in.nextLine(); System.out.println("result is:"+response); System.out.println("================================================"); } }
/** * 服务端代码 * @author suibian * */ public class ATMServer { public static void main(String[] args) throws IOException { ServerSocket socket=new ServerSocket(8888); Bank bank=new Bank(10); /*开启10个人的小银行*/ System.out.println("Server start"); while(true){ Socket s=socket.accept(); System.out.println("user join,start thread"+s.toString()); /*将对象传进去,然后交给线程处理*/ new Thread(new ServerThread(s,bank)).start(); } } }
public class ServerThread implements Runnable { private Socket s; private Bank bank; Scanner in; PrintWriter out; public ServerThread(Socket s,Bank bank){ this.s=s; this.bank=bank; } public void run() { try { InputStream instream=s.getInputStream(); in =new Scanner(instream); OutputStream stream=s.getOutputStream(); out=new PrintWriter(stream); while(true){ //死循环 String response=in.next(); /*以换行或者空格符为分界线接受下一个String类型变量*/ System.out.println("Server received command: "+response); if(response.equals("QUIT")||!in.hasNext()){ break; } deal(response); } } catch (IOException e) { e.printStackTrace(); } } private void deal(String response){ int accountId=in.nextInt(); if(response.equals("DEPOSIT")){ double amount=in.nextDouble(); //这个有意思 bank.deposit(accountId, amount); }else if(response.equals("WITHDRAW")){ double amount=in.nextDouble(); bank.withdraw(accountId, amount); }else if( !response.equals("BALANCE") ){ out.print("错误命令"); out.flush(); return; } out.println(accountId+" "+bank.getBalance(accountId)); /*返回成功语句给客户端 REBALANCE 3 1500*/ out.flush(); } }