http和socket通信的区别
其实这样比是有问题的,http实际上是一种应用级协议,常用的是http10和http 11协议。而socket则是一个连接,它直接在链路层上进行连接。在该连接的基础之可以实现各种应用级协议。如通过socket可以实现ftp协议、http、https、NetBIOS、Win、Iron等等,甚至于可以实现蓝牙(蓝牙连接在net中不被支持,是因为socket所需参数的协议簇中枚举中没有蓝牙,但可以直接通过数据,实现与蓝牙的通信)。所以http是一个协议与Socket连接是没有可比性的,在net中,可实现http协议的连接。
正是因为socket功能的强大,所以对于socket编程一般用于特殊一点的协议或高性能网络要求的情况下才使用这种编程。如果是一般的tcp/ip,在net中已经实现了其功能封装。例如WebClient实现http/https,再如net 45新增的HttpClient也可以实现同的功能。但这些功能较为狭窄,那么在net中的可插入协议是一个中庸的选择。目前实现的有HttpWebRequest/FtpWebRequest。并且可继承WebRequest实现自己的可插入协议。
也就是说,如果我们与httpClient或WebClient与Scoket相比的话,WebClinet/HttpClient是实现特定功能的Socket封装,它减少开发周期,但底层还是Socket。如果WebRequest与Socket相比的话,WebRequest是实现特定协议的Socket封闭,并可实现可插入协议。换句来说,WebClient是完完全全的一个通信类,而WebRequest则算是一个协议开发类(它已经实现了FtpWebRequest及HttpWebRequest),而Socket则是底层开发。
你这个是手机终端和pc交互吧 首先PC作为服务器是不能直接访问手机的 只有通过手机的推拉方式来实现交互 一般都是手机是主动的 http要访问固定ip 手机一般不具备所以无法作为服务器 socket虽然也是PC作为服务器 但是socket中涉及到一个推送 通过推送就是实现了PC主动想手机发送信息 而且手机端可以制作心跳包 定时向服务器请求数据 所以也可以实现伪PC主动发送(其实是手机端啦的)
1能接受HttpRequest并返回HttpResponse
2满足一个Server的基本特征,能够长时间运行
关于Http协议一般HttpServer都会声明支持Http协议的哪些特性,nanohttpd作为一个轻量级的httpserver只实现了最简单、最常用的功能,不过我们依然可以从中学习很多。
首先看下NanoHttpd类的start函数
[java] view plaincopy
public void start() throws IOException {
myServerSocket = new ServerSocket();
myServerSocketbind((hostname != null) new InetSocketAddress(hostname, myPort) : new InetSocketAddress(myPort));
myThread = new Thread(new Runnable() {
@Override
public void run() {
do {
try {
final Socket finalAccept = myServerSocketaccept();
registerConnection(finalAccept);
finalAcceptsetSoTimeout(SOCKET_READ_TIMEOUT);
final InputStream inputStream = finalAcceptgetInputStream();
asyncRunnerexec(new Runnable() {
@Override
public void run() {
OutputStream outputStream = null;
try {
outputStream = finalAcceptgetOutputStream();
TempFileManager tempFileManager = tempFileManagerFactorycreate();
HTTPSession session = new HTTPSession(tempFileManager, inputStream, outputStream, finalAcceptgetInetAddress());
while (!finalAcceptisClosed()) {
sessionexecute();
}
} catch (Exception e) {
// When the socket is closed by the client, we throw our own SocketException
// to break the "keep alive" loop above
if (!(e instanceof SocketException && "NanoHttpd Shutdown"equals(egetMessage()))) {
eprintStackTrace();
}
} finally {
safeClose(outputStream);
safeClose(inputStream);
safeClose(finalAccept);
unRegisterConnection(finalAccept);
}
}
});
} catch (IOException e) {
}
} while (!myServerSocketisClosed());
}
});
myThreadsetDaemon(true);
myThreadsetName("NanoHttpd Main Listener");
myThreadstart();
}
1创建ServerSocket,bind制定端口
2创建主线程,主线程负责和client建立连接
3建立连接后会生成一个runnable对象放入asyncRunner中,asyncRunnerexec会创建一个线程来处理新生成的连接。
4新线程首先创建了一个HttpSession,然后while(true)的执行httpSessionexec。
这里介绍下HttpSession的概念,HttpSession是java里Session概念的实现,简单来说一个Session就是一次httpClient->httpServer的连接,当连接close后session就结束了,如果没结束则session会一直存在。这点从这里的代码也能看到:如果socket不close或者exec没有抛出异常(异常有可能是client段断开连接)session会一直执行exec方法。
一个HttpSession中存储了一次网络连接中server应该保存的信息,比如:URI,METHOD,PARAMS,HEADERS,COOKIES等。
5这里accept一个client的socket就创建一个独立线程的server模型是ThreadServer模型,特点是一个connection就会创建一个thread,是比较简单、常见的socket server实现。缺点是在同时处理大量连接时线程切换需要消耗大量的资源,如果有兴趣可以了解更加高效的NIO实现方式。
当获得client的socket后自然要开始处理client发送的httprequest。
Http Request Header的parse:
[plain] view plaincopy
// Read the first 8192 bytes
// The full header should fit in here
// Apache's default header limit is 8KB
// Do NOT assume that a single read will get the entire header at once!
byte[] buf = new byte[BUFSIZE];
splitbyte = 0;
rlen = 0;
{
int read = -1;
try {
read = inputStreamread(buf, 0, BUFSIZE);
} catch (Exception e) {
safeClose(inputStream);
safeClose(outputStream);
throw new SocketException("NanoHttpd Shutdown");
}
if (read == -1) {
// socket was been closed
safeClose(inputStream);
safeClose(outputStream);
throw new SocketException("NanoHttpd Shutdown");
}
while (read > 0) {
rlen += read;
splitbyte = findHeaderEnd(buf, rlen);
if (splitbyte > 0)
break;
read = inputStreamread(buf, rlen, BUFSIZE - rlen);
}
}
1读取socket数据流的前8192个字节,因为http协议中头部最长为8192
2通过findHeaderEnd函数找到header数据的截止位置,并把位置保存到splitbyte内。
[java] view plaincopy
if (splitbyte < rlen) {
inputStreamunread(buf, splitbyte, rlen - splitbyte);
}
parms = new HashMap<String, String>();
if(null == headers) {
headers = new HashMap<String, String>();
}
1http协议规定header和body之间使用两个回车换行分割
1Http协议第一行是Method URI HTTP_VERSION
2后面每行都是KEY:VALUE格式的header
3uri需要经过URIDecode处理后才能使用
4uri中如果包含?则表示有param,httprequest的param一般表现为:/indexjspusername=xiaoming&id=2
下面是处理cookie,不过这里cookie的实现较为简单,所以跳过。之后是serve方法,serve方法提供了用户自己实现httpserver具体逻辑的很好接口。在NanoHttpd中的serve方法实现了一个默认的简单处理功能。
[java] view plaincopy
发送response的步骤如下:
1设置mimeType和Time等内容。
2创建一个PrintWriter,按照HTTP协议依次开始写入内容
3第一行是HTTP的返回码
4然后是content-Type
5然后是Date时间
6之后是其他的HTTP Header
7设置Keep-Alive的Header,Keep-Alive是Http11的新特性,作用是让客户端和服务器端之间保持一个长链接。
8如果客户端指定了ChunkedEncoding则分块发送response,Chunked Encoding是Http11的又一新特性。一般在response的body比较大的时候使用,server端会首先发送response的HEADER,然后分块发送response的body,每个分块都由chunk length\r\n和chunk data\r\n组成,最后由一个0\r\n结束。
9如果没指定ChunkedEncoding则需要指定Content-Length来让客户端指定response的body的size,然后再一直写body直到写完为止。
你可以把你的Socket服务写在一个Servele的Init方法里面,然后在webxml中配置
1
2
3
4
5
<servlet>
<servlet-name>servlet的名字</servlet-name>
<servlet-class>servlet所在的包的路径</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
就可以一起启动了。
1、先打开浏览器,选择菜单栏的工具选项,在弹出来的下拉框中选择“选项”,然后在弹出的属性框中点击“高级”选项,然后找到网络,点击,此时就来到网络设置界面,然后点击“设置”,进入配置代理界面。
2、然后就是填写代理IP和端口即可。
0条评论