简单的Socket实现的http Server

代码下载地址  http://note.youdao.com/share/?id=1d28ee946720332255efc72c3e12a0da&type=note

参考 http://blog.csdn.net/u010687392/article/details/44649589

/**
 *
 * @className: MainActivity
 * @description: 手机红外客户端:处理TV请求发射的红外码
 * @author: Administrator
 * @date: 2015年9月6日 上午9:40:13
 */
public class MainActivity extends Activity
{
    private TextView mInputText;
    ServerSocket server = null;
    Socket socket = null;
    private TextView mTitleText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTitleText = (TextView) findViewById(R.id.title);
        mInputText = (TextView) findViewById(R.id.msg);
        initServiceData();
        mTitleText.setText("IP:" + getIp());

    }

    private String getIp() {
        WifiManager wifimanger = (WifiManager) getSystemService(WIFI_SERVICE);
        WifiInfo wifiinfo = wifimanger.getConnectionInfo();
        int i = wifiinfo.getIpAddress();
        return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF) + "." + (i >> 24 & 0xFF);
    }

    private void initServiceData() {

        new Thread()
        {
            @Override
            public void run() {

                try {
                    server = new ServerSocket(8888);//创建一个ServerSocket,并让Socket监听8888的端口

                    // 调用ServerSocket的accept()方法,接受客户端所发送的请求,同时创建一个Socket对象
                    // 如果客户端没有发送数据,那么该线程就停滞不继续,也就是阻塞
                    while (true) {
                        socket = server.accept();
                        System.out.println("主机:" + socket.getInetAddress().getHostName() + ",IP:" + socket.getInetAddress().getHostAddress());//得到当前发送数据Socket对象的主机名和ip地址

                        //读取客户端的消息
                        InputStream inputStream = socket.getInputStream();
                        BufferedInputStream bis = new BufferedInputStream(inputStream);
                        //byte[] b = new byte[inputStream.available()];
                        byte[] b = new byte[1024 * 2];
                        int len = -1;
                        final StringBuilder stringBuilder = new StringBuilder();
                        while ((len = bis.read(b)) != -1) {
                            String msg = new String(b, 0, len, "UTF-8");
                            System.out.println(msg);
                            stringBuilder.append(msg);
                            break;//一次只能读取2048个自己的请求数据, 当然也可以更加content lenght计算, 然后跳出循环. 注意.这里 read(b) 永远不会是-1 因为读取到输入流末尾之后, socket还是会尝试读取client的数据
                        }

                        runOnUiThread(new Runnable()
                        {
                            @Override
                            public void run() {
                                HttpRequestParser httpRequestParser = new HttpRequestParser();
                                try {
                                    httpRequestParser.parseRequest(stringBuilder.toString());
                                    mInputText.append(stringBuilder.toString() + "\n=================\n\n");
                                    //mInputText.append(URLDecoder.decode(httpRequestParser.getMessageBody(), "UTF-8"));
                                    Log.d("TAG", "params is " + URLDecoder.decode(httpRequestParser.getMessageBody(), "UTF-8"));

                                }
                                catch (IOException e) {
                                    e.printStackTrace();
                                }
                                catch (HttpFormatException e) {
                                    e.printStackTrace();
                                }

                            }
                        });
                        socket.shutdownInput();//结束读取

                        //--------向客户端的返回信息-------------
                        OutputStream outputResult = socket.getOutputStream();
                        StringBuffer sb = new StringBuffer();
                        sb.append("HTTP/1.1 200 OK\r\n");
                        sb.append("Host: " + socket.getInetAddress().getHostName() + "\r\n");
                        sb.append("\r\n");
                        outputResult.write(sb.toString().getBytes());
                        outputResult.write("ok,received".getBytes());
                        outputResult.flush();

                        bis.close();//关闭缓存输入流,注意,输入流input不需要关闭,因为它只是在Socket中得到输入流对象,并没有创建

                        socket.close();//接收这个Socket的数据后释放资源,因为每一次客户端发送数据都会在服务端创建一个Socket对象,注意ServerSocket不应该关闭,因为这是服务器ServerSocket对象,关闭了客户端就不能发送数据了
                        socket = null;

                    }

                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();

    }
}

Http报文解析类

/**
 * Class for HTTP request parsing as defined by RFC 2612:
 *
 * Request = Request-Line ; Section 5.1 (( general-header ; Section 4.5 |
 * request-header ; Section 5.3 | entity-header ) CRLF) ; Section 7.1 CRLF [
 * message-body ] ; Section 4.3
 *
 * @author izelaya
 *
 */
public class HttpRequestParser
{

    private String _requestLine;
    private HashMap<String, String> _requestHeaders;
    private StringBuffer _messagetBody;

    public HttpRequestParser() {
        _requestHeaders = new HashMap<String, String>();
        _messagetBody = new StringBuffer();
    }

    /**
     * Parse and HTTP request.
     *
     * @param request
     *            String holding http request.
     * @throws IOException
     *             If an I/O error occurs reading the input stream.
     * @throws HttpFormatException
     *             If HTTP Request is malformed
     */
    public void parseRequest(String request) throws IOException, HttpFormatException {
        if (TextUtils.isEmpty(request)) {
            return;
        }
        BufferedReader reader = new BufferedReader(new StringReader(request));

        setRequestLine(reader.readLine()); // Request-Line ; Section 5.1

        String header = reader.readLine();
        while (header.length() > 0) {
            appendHeaderParameter(header);
            header = reader.readLine();
        }

        String bodyLine = reader.readLine();
        while (bodyLine != null) {
            appendMessageBody(bodyLine);
            bodyLine = reader.readLine();
        }

    }

    /**
     *
     * 5.1 Request-Line The Request-Line begins with a method token, followed by
     * the Request-URI and the protocol version, and ending with CRLF. The
     * elements are separated by SP characters. No CR or LF is allowed except in
     * the final CRLF sequence.
     *
     * @return String with Request-Line
     */
    public String getRequestLine() {
        return _requestLine;
    }

    private void setRequestLine(String requestLine) throws HttpFormatException {
        if (requestLine == null || requestLine.length() == 0) {
            throw new HttpFormatException("Invalid Request-Line: " + requestLine);
        }
        _requestLine = requestLine;
    }

    private void appendHeaderParameter(String header) throws HttpFormatException {
        int idx = header.indexOf(":");
        if (idx == -1) {
            throw new HttpFormatException("Invalid Header Parameter: " + header);
        }
        _requestHeaders.put(header.substring(0, idx), header.substring(idx + 1, header.length()));
    }

    /**
     * The message-body (if any) of an HTTP message is used to carry the
     * entity-body associated with the request or response. The message-body
     * differs from the entity-body only when a transfer-coding has been
     * applied, as indicated by the Transfer-Encoding header field (section
     * 14.41).
     *
     * @return String with message-body
     */
    public String getMessageBody() {
        return _messagetBody.toString();
    }

    private void appendMessageBody(String bodyLine) {
        _messagetBody.append(bodyLine).append("\r\n");
    }

    /**
     * For list of available headers refer to sections: 4.5, 5.3, 7.1 of RFC
     * 2616
     *
     * @param headerName
     *            Name of header
     * @return String with the value of the header or null if not found.
     */
    public String getHeaderParam(String headerName) {
        return _requestHeaders.get(headerName);
    }

    public class HttpFormatException extends Exception
    {

        private static final long serialVersionUID = 1L;

        public HttpFormatException(String string) {}

    }
}
时间: 2024-10-10 15:20:19

简单的Socket实现的http Server的相关文章

C# 如何实现简单的Socket通信(附示例)

上周由于有个项目需要用到网络通信这块,然后就花了点时间研究了一下,本来想上周就写出来的,但是突然要忙,所以等到现在. 话说对于网络通信,以前写C++的时候,天天面对着线程和Socket,所以换成C#也就没那么怕了,虽然C++下也没有掌握的多好,但毕竟只是一个小Demo,只作为了解一下过程. 自己写了一个服务端和一个客户端,刚开始比较简单,只是能达到连通,收发信息的目的,但是很粗糙.而后稍加改进呢~加上了多线程,所以能感觉更科学一些,不过自己真的很菜,代码写的不是很好看,下面分两个版本给大家表出来

Windows socket之最简单的socket程序

原文:Windows socket之最简单的socket程序 最简单的服务器的socket程序流程如下(面向连接的TCP连接 ): 1. WSAStartup(); 初始化网络库的使用. 2. socket(); 获得一个socket. 3. bind(); 把获得的socket绑定到一个ip 和端口.既然作为服务器, ip通常为本地IP127.0.0.1. 4. listen(); 监听已经绑定了指定端口的socket. 5. accept(); 接受一个来自客户端的连接. accept()返

简单的socket通信

//client#include <iostream> #include <WinSock2.h> #pragma comment(lib, "WS2_32") // 链接到WS2_32.lib using namespace std; int main() { SOCKET so; WSADATA ws; if (WSAStartup(MAKEWORD(2, 2), &ws) != 0) { cout << "WSAStartup

Linux下简单的socket通信实例

Linux下简单的socket通信实例 If you spend too much time thinking about a thing, you’ll never get it done. —Bruce Lee       学习网络编程也一段时间了,刚开始看<UNIX网络编程>的时候,觉得这本厚厚的书好难啊!看到后来,发现并没有想象中的那么难.如果你是新手,建议你看到第二部分结束后,开始着手写代码.不写代码肯定是不行的.看100遍也没有敲一遍实现一遍来的清楚.敲完以后,带着问题去看书,你会

Android开发socket通信——手机做server端C/S架构实现

每一部智能手机都是一部微型电脑,在学校里最喜欢的就是找上十个八个同学一起局域网内开几局dota,突然想到,拿手机C一个游戏来玩怎样,不用连wifi.不用开数据,几部手机选一个做主机,其他手机连上它的热点,便可以互动起来游戏搞起来了,多开心~~ 实际实现过程中发现拿手机本身做server的手段还真是很少有人使用,网上也很少有现成的解决方案,经过一番摸索,简单实现了手机自身做server(可兼做客户端)的socket通信功能,写出来请大家指导一下,也是简单梳理一下方便日后复用. 遇到的最大问题可能是

拿nodejs快速搭建简单Oauth认证和restful API server攻略

拿nodejs快速搭建简单Oauth认证和restful API server攻略:http://blog.csdn.net/zhaoweitco/article/details/21708955 最近一直在鼓捣这个东西,拿出来分享下一下经验吧,其实很简单,一点也不难. 首先需求是这样,给自己的网站要增加API服务,API分为两种,公共的和私有授权的,授权的使用Oauth方法认证身份,API格式均为JOSN和JSONP. 嗯,别的语言我也没怎么学过,首先是找合适的框架进行实现吧.本身网站使用的e

一个最简单的Socket通信例子

所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过"套接字"向网络发出请求或者应答网络请求.  Socket和ServerSocket类库位于java.net包中.ServerSocket用于服务器端,Socket是建立网络连接时使用的.在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话.对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别.不管是

ActionScript简单实现Socket Tcp应用协议分析器

转自..smark http://www.cnblogs.com/smark/archive/2012/05/15/2501507.html ActionScript简单实现Socket Tcp应用协议分析器 其实Flash上做通讯很多情况都选择AMF,毕竟他是AS内部基于对象进制序列协议,容量小效率高.但有时为了去调用一些已经有的Tcp服务,而这些服务并不是提供AMF支持:这时你就不得不实现一个协议的分析.其实AS提ByteArray提供了很多write和read方法,这样使我们应用起来非常方

C#版 Socket编程(最简单的Socket通信功能)

原文://http://blog.csdn.net/linybo/article/details/51141960 示例程序是同步套接字程序,功能很简单,只是客户端发给服务器一条信息,服务器向客户端返回一条信息:这里只是一个简单的示例,是一个最基本的socket编程流程,在接下来的文章中,会依次记录套接字的同步和异步,以及它们的区别. 第一步:用指定的端口号和服务器的ip建立一个EndPoint对像: 第二步:建立一个Socket对像: 第三步:用socket对像的Bind()方法绑定EndPo