Java中socket使用

1. 什么是socket

所谓socket通常也称作”套接字”,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过”套接字”向网络发出请求或者应答网络请求。

以J2SDK-1.3为例,Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过 SocketImpl类及其子类完成的。

重要的Socket API:

java.net.Socket继承于java.lang.Object,有八个构造器,其方法并不多,下面介绍使用最频繁的三个方法,其它方法大家可以见JDK-1.3文档。

.Accept方法用于产生”阻塞”,直到接受到一个连接,并且返回一个客户端的Socket对象实例。”阻塞”是一个术语,它使程序运行暂时”停留”在这个地方,直到一个会话产生,然后程序继续;通常”阻塞”是由循环产生的。

.getInputStream方法获得网络连接输入,同时返回一个IutputStream对象实例。

.getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。

注意:其中getInputStream和getOutputStream方法均会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。

socket主要用于数据的传输,例如我们可以在服务器上利用socket搭建一个服务端,监听某个端口,这样外部就可以通过连接这个端口访问我们服务器上的资源,现在socket用于比较广泛的是聊天工具

2. socket的使用

下面是一个我写的用于实现一个通过接口获取数据的例子

1)  服务端

说明:监听某个端口,当有客服端连接的时候,启动一个线程用于处理连接客服端的请求,实现数据传输。

数据传输:首先先读取客服端传来的信息,根据信息获取相应的数据,再将数据传输给客服端。

package com.jjt;

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 org.apache.log4j.Logger;
import com.business.StatusContext;

public class StatusServer {

    private static Logger logger = Logger.getLogger(StatusServer.class);
    private static final int PORT = 5432;

    private static int clientCount = 0;

    public static void main(String[] args) {
        new StatusServer().connect();
    }

    /**
     * 启动服务
     */
    private void connect() {
        try {
            ServerSocket ss = new ServerSocket(PORT);
            logger.info("服务器启动");
            logger.info("*************************************");
            while(true) {
                try {
                    Socket socket = ss.accept();
                    System.out.println("client count: " + (++clientCount));
                    new Thread(new SocketThread(socket)).start();
                } catch (Exception e) {
                    logger.error("客户端接受出错:" + e);
                }
            }
        } catch (IOException e) {
            logger.error("服务器启动失败:" + e);
        }
    }
}

class SocketThread implements Runnable {
    private static Logger logger = Logger.getLogger(SocketThread.class);

    private Socket socket = null;
    InputStream in = null;
    InputStreamReader isr = null;
    BufferedReader br = null;
    OutputStream os = null;
    PrintWriter pw = null;

    public SocketThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            String msg = this.readMessage();
            if(msg != null) {
                StatusContext satatusContext = new StatusContext();
                String XMLData = satatusContext.obtainXMLData(msg);
                this.writeMessage(XMLData);
                this.socket.close();
                //this.closeStream();
            }
        } catch (Exception e) {
            logger.error("读写信息出错:" +e);
        }
    }

    /**
     * 从客户端读取信息
     */
    private String readMessage(){
        String message = null;
        try {
            in = socket.getInputStream();
            Request request = new Request(in);
            request.parse();
            message = request.getUri();
            if(message == null) return null;
            String[] msgArr = message.split("\\?");
            if(msgArr.length != 2) return null;
            message = msgArr[0].replace("/", "") + "#" + msgArr[1];
        } catch (Exception e) {
            logger.error("读取信息出错:"+ e);
            return null;
        }
        return message;
    }

    /**
     * 向客户端写入信息
     */
    private boolean writeMessage(String msg){
        boolean isSuccess = false;
        try {
            os = socket.getOutputStream();
            pw = new PrintWriter(os);
            pw.println(msg);
            pw.flush();
            os.flush();
            isSuccess = true;
        } catch (Exception e) {
            logger.error("写入信息出错:" + e);
        } 
        return isSuccess;
    }

    private void closeStream() {
        try {
            br.close();
            isr.close();
            in.close();
            pw.close();
            os.close();
            socket.close();
        } catch (Exception e) {
            logger.error("关闭连接出错:" + e);
        }
    }

}

 

2)  客服端

说明:首先连接服务端,先写入向服务端发送的数据,再读取服务端传来的数据信息

package com.jjt;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import org.apache.log4j.Logger;
import com.tool.FltDefine;

public class SocketClient {
    private static Logger logger = Logger.getLogger(StatusServer.class);
    private Socket socket = null;
    OutputStream os = null;
    PrintWriter pw = null;
    InputStream in = null;
    InputStreamReader isr = null;
    BufferedReader br = null;

    public static void main(String[] args) {
        try {
            new SocketClient().connectServer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 连接服务器端
     */
    private void connectServer() throws Exception {
        String key = "aaaa";
        String parmas = "bb=cc&dd=ee";

        String message = key + "#" + parmas;
        socket = new Socket("127.0.0.1", 5432);
        if(this.writeMessage(message)) {
            System.out.println(this.readMessage());
        }
        this.closeStream();
    }

    /**
     * 向服务端写入信息
     */
    private boolean writeMessage(String msg){
        boolean isSuccess = false;
        try {
            os = socket.getOutputStream();
            pw = new PrintWriter(os);
            pw.println(msg);
            pw.flush();
            os.flush();
            isSuccess = true;
        } catch (Exception e) {
            logger.error("写入信息出现:" + e);
        } 
        return isSuccess;
    }

    /**
     * 从服务端读取信息
     */
    private String readMessage(){
        boolean isStop = false;
        String message = null;
        try {
            in = socket.getInputStream();
            isr = new InputStreamReader(in);
            br = new BufferedReader(isr);
            while(true && !isStop) {
                message = br.readLine();
                if(message != null) {
                    isStop = true;
                }
            }
        } catch (Exception e) {
            logger.error("读取信息出错:"+ e);
            return null;
        }
        return message;
    }

    private void closeStream() {
        try {
            br.close();
            isr.close();
            in.close();
            pw.close();
            os.close();
            socket.close();
        } catch (Exception e) {
            logger.error("关闭连接出错:" + e);
        }
    }

}

 

3)  附加类

说明:当我们直接在浏览器上敲上连接服务端的地址,我们需要对这个地址进行解析,因为通过浏览器传给服务器的内容与直接用程序连接是不同的,在服务端readMessage()方法中用用到这个类

package com.jjt;

import java.io.InputStream;
import java.io.IOException;

public class Request {

    private InputStream input;
    private String uri;

    public Request(InputStream input) {
        this.input = input;
    }

    public void parse() {
        // Read a set of characters from the socket
        StringBuffer request = new StringBuffer(2048);
        int i;
        byte[] buffer = new byte[2048];
        try {
            i = input.read(buffer);
        } catch (IOException e) {
            e.printStackTrace();
            i = -1;
        }
        for (int j = 0; j < i; j++) {             request.append((char) buffer[j]);         }         uri = parseUri(request.toString());     }     private String parseUri(String requestString) {         int index1, index2;         index1 = requestString.indexOf(' ');         if (index1 != -1) {             index2 = requestString.indexOf(' ', index1 + 1);             if (index2 > index1)
                return requestString.substring(index1 + 1, index2);
        }
        return null;
    }

    public String getUri() {
        return uri;
    }

}

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>