网络编程:Java Socket通信实现(一)

Socket是什么

    Socket 也叫“套接字”,是两台机器间通信的端点,也就是成对存在才能通信。Socket 本质是编程接口,对TCP/IP的封装。
    如果说HTTP是轿车,提供了封装或者显示数据的具体形式;Socket 就是发动机,提供了网络通信的能力。(来自网络)

(来自网络)

    在Java 开发中使用Socket 时会常用到两个类,都在java.net 包中:Socket和ServerSocket
    ServerSocket用于服务端,Socket 刚是哪里都得使用,它是连接建立后的实例所对应的类。在两个应用程序连接成功时,这两个应用程序两端都会产生一个Socket 实例,我们就是通过操作这两个实例来完成通信的内容的。需要说明的是,Socket和ServerSocket并没什么差别,它们的具体实现都是通过子类SocketImpl来完成。

Socket 连接过程


总的来说分三步:服务器监听,客户端请求,连接确认
1.服务端的Socket 并不定位具体客户端的Socket,而是将自己处于一个等待连接的状态,监听网络的连接状态。
2.客户端Socket想提出连接请求,那它就得说明连接的服务器地址和端口号。
3.服务器Socket监听到客户端连接请求后,会响应客户端Socket 的请求了。它在此时会建立一个新的线程,把服务器的Socket 描述发给客户端,客户端确认了此描述,连接就算建立好了。服务器的Socket 会继续它的监听状态,等待其他连接。

Socket Java例子


服务端

package com.hlm.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;

public class SocketServer {
    
    public static void main(String[] args) throws IOException{
                
            //创建Socket
            @SuppressWarnings("resource")
            ServerSocket ssocket = new ServerSocket(888);
            System.out.println("《服务器》:服务器已开启,想连的小伙伴抓紧时间啦!");
            //等待连接的Socket,他在等生成实例,生成了便说明有连接成功了
            Socket socket ;
            while(true){
                socket = ssocket.accept();    
                //每接收到一个客户端连接刚创建一个线程来处理该连接的情况
                Thread t = new Thread(new MyRunnable(socket));
                t.start();
            }            
    }
    
    //模仿数据库存用户的账号和密码
    public static HashMap<String ,String> accountMap = new HashMap<String ,String>();
    static{
            accountMap.put("小明","123456");
            accountMap.put("小红","888888");
            accountMap.put("小强","666666");
            accountMap.put("王二","987654");
    }    
}

//创建一个内部类来为每个连接处理线程情况
class MyRunnable implements Runnable{
    Socket socket ;
    
    public MyRunnable(){ }
    
    public MyRunnable(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
        if(socket == null ){
            return ;
        }
        InputStream ins = null;
        BufferedReader br = null;
        OutputStream os = null;
        PrintWriter pw = null;
        try {
            //连接上之后获取对方传过来的信息
             ins = socket.getInputStream();
            //将字节流转为字符
             br = new BufferedReader(new InputStreamReader(ins));
            
            StringBuffer info = new StringBuffer();
            String linedata = null;
            //将信息收信进info
            while((linedata = br.readLine() ) != null){
                info.append(linedata);
            }
            String name = "";
            String password = "";
            String resultStr="错误的用户名或密码 ";
            //"name:小明;password:123456"
            //将信息按约定的解析
            String[] list = info.toString()==null?null:info.toString().split(";");
            for(String str : list){
                if(str.startsWith("name:")){
                    name = str.replace("name:", "");
                }else if(str.startsWith("password:")){
                    password = str.replace("password:", "");
                }
            }
            String mypassword = SocketServer.accountMap.get(name);
            if(mypassword !=null && mypassword.equals(password)){
                resultStr = "登录成功!";
            }
            //关闭接收数据
            socket.shutdownInput();            
            
            //将结果返回给客户端
             os = socket.getOutputStream();
             pw = new PrintWriter(os);
            pw.write(resultStr);
            System.out.println("《服务器》:请求内容为-->"+info+";请求结果为-->"+resultStr);
            //将结果刷走
            pw.flush();
            //关闭输出流
            socket.shutdownOutput();
            
        } catch (IOException e) {
            
            e.printStackTrace();
        }finally{
            //关闭所在资源(与创建反序)            
            try {
                pw.close();
                os.close();
                br.close();
                ins.close();
                if(null != socket)  {
                    socket.close();     
                }                   
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }            
        }                                
    }
    
}

客户端

package com.hlm.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class SocketClient {

    public static void main(String[] args) throws UnknownHostException, IOException {
        
        //小明登录
        getSocket(1 , "name:小明;password:123456");
        //小红登录
        getSocket(2 , "name:小红;password:888888");
        //小强登录
        getSocket(3 , "name:小强;password:666666");
        //王二登录
        getSocket(4 , "name:王二;password:忘了");
        //老王登录
        getSocket(5 , "name:老王;password:123456");

    }
    
    /**
     * 建立Socket 连接方法
     * @param num
     * @param msg
     */
    public static void getSocket(int num , String msg) {
        BufferedReader br = null;
        InputStream ins = null;
        PrintWriter pw = null;
        OutputStream os = null;
        Socket sk = null ;
        try{
            String address = "localhost";
            int  port = 888;
            System.out.println("《客户端"+num+"》:我要登录啦!");
             sk = new Socket(address,port);
             os = sk.getOutputStream();
             pw = new PrintWriter(os);
            //pw.write("name:小明;password:123456");
            pw.write(msg);
            pw.flush();
            sk.shutdownOutput();
             ins = sk.getInputStream();
             br = new BufferedReader(new InputStreamReader(ins));
            String str = null ;
            StringBuffer sb = new StringBuffer();
            while((str = br.readLine()) !=null){
                sb.append(str);
            }
            System.out.println("《客户端"+num+"》:返回的结果为-->"+sb);
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            try {
                br.close();
                pw.close();
                ins.close();
                br.close();
                if(null != sk)  {
                    sk.close();     
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            
        }
    }

}
启动服务器后
运行客户端
此时服务器打印


Socket 的更多API可以查询:


20180609

猜你喜欢

转载自blog.csdn.net/mottohlm/article/details/80638421