webservice、socket、http 、json傻傻分不清楚

一 webservice原理

第一部分直观概述

WebService的几种概念:

以HTTP协议为基础,通过XML进行客户端和服务器端通信的框架/组件

两个关键点:

1.       服务端提供的功能, 通过xml描述

2.       第一步中的描述的功能, 嵌入到HTTP协议中, 使得能通过HTTP协议进行通信【所谓的SOAP】.

用图可以如下表示:

图一: WebService的简要表示

采用这两个技术的目的主要是:

1.       跨平台, 支持HTTP协议的主机和服务器, 都能够建立通信联系, 并且大部分的主机和服务器(99.999%以上)将支持HTTP协议。一般而言,不同目标主机之间的通信,需要通过防火墙,打开某个端口, HTTP协议的优势在于,防火墙一般不会封掉80端口, 这样就可以方便,安全的通信。

2.       跨语言, 任何语言, 都支持XML文本解析, 这个的目的是为了实现不同语言之间的通信, 通信的内容,是被xml限制的,因此这样进行通信,能跨越语言障碍,即, Java开发的服务端,客户端可以用C访问, 可以用java,VB等访问, 反之亦然。

第二部分: 基本原理和架构

当然,架构比我们上面说到的图要更为复杂,上面只是说明了一来一回的通信, 实际情况还需要考虑以下问题, 参照图例说明:

1. 服务器端(Provider) 提供统一的标准化服务。就像开办一个公司(即Server Provider), 工商行政管理局,注册一下公司地址和性质。目的是, 别人要用公司的服务,从工商管理局就知道你的地址。这样统一的做法,是方便所有的公司以及所有需要公司提供服务的客户。并且这些信息是最大限度的公开。

2. 客户端(Requester) 到注册中心(Registry)拿到公司的基本信息之后, 去找到这个公司, 然后使用该公司提供的服务。

图二: 基本的WebService架构流程图

注意上面图中的基本步骤的标号, 解释如下

1. Provider节点提供好服务后, 首先注册到节点Registry

2和3. Requester节点到Regitry节点查信息, 找到需要的Provider及其提供的Service

4. Requester使用Provider提供的服务

更具体的介绍, 参照参考文献[2], 下面这些基本由这个参考文献翻译而来:

图三: 细节步骤流程图

上图这些东西, 完完整整的呈现了WebService的整个原理流程:

1.       Client有需要,想调用一个服务,但不知道哪里去调用. 但知道UDDI Registry上可以查到。

2.       果然UDDI记录了某个一个叫做Web Server A的服务器能提供这样的服务。

3.       于是Client去Web Server A, 询问确切的调用方法。

4.       Web Server A看到Client提出的“确切方法查询”之后,立即返回给它一个WSDL描述的xml文档这里记录他能提供的各类方法接口.

5.       Client了解到这些之后,将这些xml的接口方法,封装成为HTTP请求, 发给Web Server A. 这些封装方式采用的是标准的SOAP方式, 实质是满足HTTP协议的一些SOAP的报文消息。

6.       Web Server A回应的也是HTTP协议的SOAP包. 这样双方的请求-响应完全畅通。

上面我们看到的是应用原理图, 进一步深入, 可以发现如下的协议架构图:

图四: 协议结构

上面我们已经花了很大的精力, 介绍了发现Service(UDDI), Service提供的接口描述(WSDL), 调用Service(SOAP), 以及传输(HTTP)的的整个过程。因此不再做介绍。这个技术的核心是SOAP.

第三部分实践WebService

看到上面的图那么复杂, 实质上SOAP+HTTP协议已经足够成熟,犯不着让我们通过xml生成带有SOAP变迁的HTML脚本, 有很多工具可以帮住我们实现。事实上,开发起来还是相当简便的。

情况A: 已知存在Web Service, 客户端的开发可以通过以下步骤:

  1. 通过UDDI,查找到Client程序需要的Web Service的位置
  2. 通过WebService找到 WSDL接口描述文件
  3. 通过工具,将步骤2得到的WSDL文件,生成一个Client Stub, 这个实质上是代码, 也就是打了一个桩。把这个stub的代码归并到Client程序中.
  4. 每次Client需要调用WebService的时候,直接调用步骤4生成的Stub 接口,就实现了对Server端的调用。

情况B: Server端的开发,同样无需做解析SOAP这样的破事,框架会帮我们做好。大致步骤如下:

  1. 实现WebServer需要提供的所有功能

2.       利用WSDL文件(或者IDL)生成Server Stub, 这些代码将负责接收从外界获得的请求,并将其转发给Web Server的Service Implementation(实现代码)。当Service Implementation的代码处理完,产生结果之后,又会把结果交给Server Stub, 然后 Server Stub可以产生一个SOAP的响应. Server Stub + Server Implementation 合在一起, 称为Web Service Container, 这玩意儿就是让发送到WebService的HTTP请求,直接送到Server Stub上面的。

图五:实际应用中的调用

参考资料:

二、socket原理

对TCP/IP、UDP、Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵。那么我想问:

1.         什么是TCP/IP、UDP?
2.         Socket在哪里呢?
3.         Socket是什么呢?
4.         你会使用它们吗?

什么是TCP/IP、UDP

         TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
         UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。
        这里有一张图,表明了这些协议的关系。

                                                                                

                                                                        图1

       TCP/IP协议族包括运输层、网络层、链路层。现在你知道TCP/IP与UDP的关系了吧。
Socket在哪里呢?
       在图1中,我们没有看到Socket的影子,那么它到底在哪里呢?还是用图来说话,一目了然。



图2

       原来Socket在这里。
Socket是什么呢?
       Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
你会使用它们吗?
       前人已经给我们做了好多的事了,网络间的通信也就简单了许多,但毕竟还是有挺多工作要做的。以前听到Socket编程,觉得它是比较高深的编程知识,但是只要弄清Socket编程的工作原理,神秘的面纱也就揭开了。
       一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。    生活中的场景就解释了这工作原理,也许TCP/IP协议族就是诞生于生活中,这也不一定。

      

图3

       先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

============================================

我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页 时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠socket?那什么是 socket?socket的类型有哪些?还有socket的基本函数,这些都是本文想介绍的。本文的主要内容如下:

  • 1、网络中进程之间如何通信?

  • 2、Socket是什么?

  • 3、socket的基本操作

    • 3.1、socket()函数

    • 3.2、bind()函数

    • 3.3、listen()、connect()函数

    • 3.4、accept()函数

    • 3.5、read()、write()函数等

    • 3.6、close()函数

  • 4、socket中TCP的三次握手建立连接详解

  • 5、socket中TCP的四次握手释放连接详解

  • 6、一个例子

1、网络中进程之间如何通信?

本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类:

  • 消息传递(管道、FIFO、消息队列)

  • 同步(互斥量、条件变量、读写锁、文件和写记录锁、信号量)

  • 共享内存(匿名的和具名的)

  • 远程过程调用(Solaris门和Sun RPC)

但这些都不是本文的主题!我们要讨论的是网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的。其实TCP/IP协议族已经帮我们解决了这个问题,网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。

使用TCP/IP协议的应用程序通常采用应用编程接口:UNIX BSD的套接字(socket)和UNIX System V的TLI(已经被淘汰),来实现网络进程之间的通信。就目前而言,几乎所有的应用程序都是采用socket,而现在又是网络时代,网络中进程通信是无处不在,这就是我为什么说“一切皆socket”。

2、什么是Socket?

上面我们已经知道网络中的进程是通过socket来通信的,那什么是socket呢?socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭),这些函数我们在后面进行介绍。

socket一词的起源

在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的,撰写者为Stephen Carr、Steve Crocker和Vint Cerf。根据美国计算机历史博物馆的记载,Croker写道:“命名空间的元素都可称为套接字接口。一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定。”计算机历史博物馆补充道:“这比BSD的套接字接口定义早了大约12年。”

3、socket的基本操作

既然socket是“open—write/read—close”模式的一种实现,那么socket就提供了这些操作对应的函数接口。下面以TCP为例,介绍几个基本的socket接口函数。

3.1、socket()函数

int socket(int domain, int type, int protocol);

socket函数对应于普通文件的打开操作。普通文件的打开操作返回一个文件描述字,而socket()用于创建一个socket描述符(socket descriptor),它唯一标识一个socket。这个socket描述字跟文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。

正如可以给fopen的传入不同参数值,以打开不同的文件。创建socket的时候,也可以指定不同的参数创建不同的socket描述符,socket函数的三个参数分别为:

  • domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
  • type:指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等(socket的类型有哪些?)。
  • protocol:故名思意,就是指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议(这个协议我将会单独开篇讨论!)。

注意:并不是上面的type和protocol可以随意组合的,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。

当我们调用socket创建一个socket时,返回的socket描述字它存在于协议族(address family,AF_XXX)空间中,但没有一个具体的地址。如果想要给它赋值一个地址,就必须调用bind()函数,否则就当调用connect()、listen()时系统会自动随机分配一个端口。

3.2、bind()函数

正如上面所说bind()函数把一个地址族中的特定地址赋给socket。例如对应AF_INET、AF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

函数的三个参数分别为:

  • sockfd:即socket描述字,它是通过socket()函数创建了,唯一标识一个socket。bind()函数就是将给这个描述字绑定一个名字。
  • addr:一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同,如ipv4对应的是:
    struct sockaddr_in {
        sa_family_t    sin_family; 
        in_port_t      sin_port;   
        struct in_addr sin_addr;   
    };
    
    
    struct in_addr {
        uint32_t       s_addr;     
    };
    
    ipv6对应的是:
    struct sockaddr_in6 { 
        sa_family_t     sin6_family;    
        in_port_t       sin6_port;      
        uint32_t        sin6_flowinfo;  
        struct in6_addr sin6_addr;      
        uint32_t        sin6_scope_id;  
    };
    
    struct in6_addr { 
        unsigned char   s6_addr[16];    
    };
    
    Unix域对应的是:
    #define UNIX_PATH_MAX    108
    
    struct sockaddr_un { 
        sa_family_t sun_family;                
        char        sun_path[UNIX_PATH_MAX];   
    };
    
  • addrlen:对应的是地址的长度。

通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。

网络字节序与主机字节序

主机字节序就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。引用标准的Big-Endian和Little-Endian的定义如下:

  a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

  b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

网络字节序:4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序。由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。字节序,顾名思义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序,一个字节的数据没有顺序的问题了。

所以: 在将一个地址绑定到socket的时候,请先将主机字节序转换成为网络字节序,而不要假定主机字节序跟网络字节序一样使用的是Big-Endian。由于 这个问题曾引发过血案!公司项目代码中由于存在这个问题,导致了很多莫名其妙的问题,所以请谨记对主机字节序不要做任何假定,务必将其转化为网络字节序再 赋给socket。

3.3、listen()、connect()函数

如果作为一个服务器,在调用socket()、bind()之后就会调用listen()来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求。

int listen(int sockfd, int backlog);
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数。socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。

connect函数的第一个参数即为客户端的socket描述字,第二参数为服务器的socket地址,第三个参数为socket地址的长度。客户端通过调用connect函数来建立与TCP服务器的连接。

3.4、accept()函数

TCP服务器端依次调用socket()、bind()、listen()之后,就会监听指定的socket地址了。TCP客户端依次调用socket()、connect()之后就想TCP服务器发送了一个连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数取接收请求,这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作。

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

accept函数的第一个参数为服务器的socket描述字,第二个参数为指向struct sockaddr *的指针,用于返回客户端的协议地址,第三个参数为协议地址的长度。如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与返回客户的TCP连接。

注意:accept的第一个参数为服务器的socket描述字,是服务器开始调用socket()函数生成的,称为监听socket描述字;而accept函数返回的是已连接的socket描述字。一个服务器通常通常仅仅只创建一个监听socket描述字,它在该服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字,当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭。

3.5、read()、write()等函数

万事具备只欠东风,至此服务器与客户已经建立好连接了。可以调用网络I/O进行读写操作了,即实现了网咯中不同进程之间的通信!网络I/O操作有下面几组:

  • read()/write()
  • recv()/send()
  • readv()/writev()
  • recvmsg()/sendmsg()
  • recvfrom()/sendto()

我推荐使用recvmsg()/sendmsg()函数,这两个函数是最通用的I/O函数,实际上可以把上面的其它函数都替换成这两个函数。它们的声明如下:

       #include 

       ssize_t read(int fd, void *buf, size_t count);
       ssize_t write(int fd, const void *buf, size_t count);

       #include 
       #include 

       ssize_t send(int sockfd, const void *buf, size_t len, int flags);
       ssize_t recv(int sockfd, void *buf, size_t len, int flags);

       ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);
       ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

       ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
       ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0表示已经读到文件的结束了,小于0表示出现了错误。如果错误为EINTR说明读是由中断引起的,如果是ECONNREST表示网络连接出了问题。

write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节 数。失败时返回-1,并设置errno变量。在网络程序中,当我们向套接字文件描述符写时有俩种可能。1)write的返回值大于0,表示写了部分或者是 全部的数据。2)返回的值小于0,此时出现了错误。我们要根据错误类型来处理。如果错误为EINTR表示在写的时候出现了中断错误。如果为EPIPE表示 网络连接出现了问题(对方已经关闭了连接)。

其它的我就不一一介绍这几对I/O函数了,具体参见man文档或者baidu、Google,下面的例子中将使用到send/recv。

3.6、close()函数

在服务器与客户端建立连接之后,会进行一些读写操作,完成了读写操作就要关闭相应的socket描述字,好比操作完打开的文件要调用fclose关闭打开的文件。

#include 
int close(int fd);

close一个TCP socket的缺省行为时把该socket标记为以关闭,然后立即返回到调用进程。该描述字不能再由调用进程使用,也就是说不能再作为read或write的第一个参数。

注意:close操作只是使相应socket描述字的引用计数-1,只有当引用计数为0的时候,才会触发TCP客户端向服务器发送终止连接请求。

4、socket中TCP的三次握手建立连接详解

我们知道tcp建立连接要进行“三次握手”,即交换三个分组。大致流程如下:

  • 客户端向服务器发送一个SYN J
  • 服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1
  • 客户端再想服务器发一个确认ACK K+1

只有就完了三次握手,但是这个三次握手发生在socket的那几个函数中呢?请看下图:

image

图1、socket中发送的TCP三次握手

从图中可以看出,当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。

总结:客户端的connect在三次握手的第二个次返回,而服务器端的accept在三次握手的第三次返回。

5、socket中TCP的四次握手释放连接详解

上面介绍了socket中TCP的三次握手建立过程,及其涉及的socket函数。现在我们介绍socket中的四次握手释放连接的过程,请看下图:

image

图2、socket中发送的TCP四次握手

图示过程如下:

  • 某个应用进程首先调用close主动关闭连接,这时TCP发送一个FIN M;

  • 另一端接收到FIN M之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据;

  • 一段时间之后,接收到文件结束符的应用进程调用close关闭它的socket。这导致它的TCP也发送一个FIN N;

  • 接收到这个FIN的源发送端TCP对它进行确认。

这样每个方向上都有一个FIN和ACK。

6.下面给出实现的一个实例

首先,先给出实现的截图

三、RPC、WebService、Restful、Json、Xml这些概念之间的关系

RPC有2层含义:

(1)      (协议层)编码方式

(2)      (传输层)传输方式

RPC

协议层\传输层

TCP

WebSocket

Http(WebService)

文本

XML

/

/

Xml-Http(SOAP)

Json

Json-RPC(TCP)

Json-RPC(WebSocket)

Json-Http

Yaml

*

*

*

WSDL

/

/

*

*

/

/

Corba

*

/

/

RMI

2进制

Thrift

Thrift

/

/

Protobuf

Protobuf

gRPC

MsgPack

MsgPack

/

/

hessian

hessian

/

/

dobbo

dobbo

/

/

RestFul

有些概念(技术)之间的关系不适合比较,因为不属于同一个层次;比如Restful、WebService, etc。

众所周知,Json-RPC很普遍;但是Json-RPC并没有限制承载协议,不必只能用Http,WebSocket、TCP照样可以。

有一个地方大家误会很多,Restful,以为与Http关系严密就像搞基;其实,RestFul也没有限制承载协议(会话层协议),不必非要Http,满足Restful的原则即可。

另外,RestFul并非什么新鲜东西,其实满大街都是;我们能看见的Web服务,大多数是RestFul的,只不过实现不像RestFul期望得那么完整。

(图表里,对Corba、RMI的归类很大可能是错的,对于这些老古董,其实不必太关心)

四、webservice、socket、http 、json_conganguo的专栏-CSDN博客

一、

webservice是基于http协议的soap协议的封装和补充,如果你考虑公共稳定的接口,你可以努力的考虑一下。
至于socket和http、webservices是否放在一起比较和考虑
主要还是看你关心的角度,而这个角度可以是技术层面的 ,也可以是用户需求层面

1 数据传输方式
1.1 socket传输的定义和其特点
    所谓socket通常也称作"套接字",实现服务器和客户端之间的物理连接,并进行数据传输,主要有udp和tcp两个协议。socket处于网络协议的传输层。
    udp协议:广播式数据传输,不进行数据验证
    tcp协议:传输控制协议,一种面向连接的协议,给用户进程提供可靠的全双工的字节流,

socket传输的特点:
   优点
   1) 传输数据为字节级,传输数据可自定义,数据量小(对于手机应用讲:费用低)
   2) 传输数据时间短,性能高
   3) 适合于客户端和服务器端之间信息实时交互
   4) 可以加密,数据安全性强
   缺点:
   1) 需对传输的数据进行解析,转化成应用级的数据
   2) 对开发人员的开发水平要求高
   3) 相对于http协议传输,增加了开发量

1.2 基于http协议传输的定义和其特点

   目前基于http协议传输的主要有http协议 和基于http协议的soap协议(web service),常见的方式是 http 的post 和get 请求,web 服务。

基于http协议的传输特点
   优点:
   1) 基于应用级的接口使用方便
   2) 程序员开发水平要求不高,容错性强
   缺点:
   1) 传输速度慢,数据包大(http协议中包含辅助应用信息)

   2) 如实时交互,服务器性能压力大。

   3) 数据传输安全性差

2 各数据传输方式的适用范围
 2.1 socket传输适用范围
  基于socket传输的特点:socket 传输方式适合于对传输速度,安全性,实时交互,费用等要求高的应用中,如网络游戏,手机应用,银行内部交互等
 2.2 基于http协议传输的适用范围
  基于http协议传输的特点:基于http协议传输方式适合于对传输速度,安全性
  要求不是很高,且需要快速开发的应用。如公司oa系统,互联网服务等

我觉得把socket和http、webservices等等放在一起对比不是很合适,所谓http云云的都是对socket进行了一次包装而已,后者更加底层。不过对比http和webservices的异同点的话
 

二、

socket和webservice都有跨平台的优点,但是:
        socket偏底层,效率高,但是开发成本大。
        webservice效率低,但是开发成本低廉。
webservice,基于http协议,以xml为载体的通信方式。
    好处,一直观,二标准,也方便异构系统的交互。
    如果想提供对外的业务访问的接口,可能需要浏览器,各种语言的客户端等各种异构系统访问,是首选。
socket,提供了tcp/ip或者udp的通信的实现,如果做标准的服务器,比如下载服务器;或者语音通信的程序,或者视频,文件传输……这些只能用socket。
单纯用socket写会很烦的,你要处理各种东西,协议的编解码等等,所以这种情况下推荐mina,netty或者grizzly。
Json,本质来说它就是javascript片段描述对象,对浏览器很有用。如果要做一个ajax的功能的话,json是最简单有效而且性能好。比如mtime的很多异步功能都是用json方式传递的。json没有什么门槛,也可以用于异构系统交互,不过如果异构系统不仅仅是浏览器,那还是选择webservice。jsonlib等库都可以直接把一个对象转为json字符串,struts2也提供了json插件,