SOAP和HTTP关系
SOAP:简单对象访问协议是交换数据的一种协议规范,是一种轻量的、简单的、基于XML(标准通用标记语言下的一个子集)的协议,它被设计成在WEB上交换结构化的和固化的信息。
构建模块
一条 SOAP 消息就是一个普通的 XML 文档,包含下列元素:
必需的 Envelope 元素,可把此 XML 文档标识为一条 SOAP 消息
可选的 Header 元素,包含头部信息
必需的 Body 元素,包含所有的调用和响应信息
可选的 Fault 元素,提供有关在处理此消息所发生错误的信息
语法规则
这里是一些重要的语法规则:
SOAP 消息必须用 XML 来编码
SOAP 消息必须使用 SOAP Envelope 命名空间
SOAP 消息必须使用 SOAP Encoding 命名空间
SOAP 消息不能包含 DTD 引用
SOAP 消息不能包含 XML 处理指令
HTTP:HTTP协议目的是规定客户端和服务端数据传输的格式和数据交互行为,并不负责数据传输的细节。底层是基于TCP实现的。
常用的请求方法:GET/POST/DELETE/PUT
常见的响应的状态码:200OK/400Bad Request/403Forbidden/404Not Found/500Internal Server Error/
HTTP是一个通信协议,通过网络传输信息。
SOAP
是一个基于XML的协议交换消息,可以使用HTTP来传输这些信息。事实上HTTP是SOAP消息的最常见的传输工具。soap将信息进行XML的序列化后,再用http协议的方式再打包进行传送,传送的方式还是tcp或者udp。
SOAP采用了已经广泛使用的两个协议:HTTP 和XML(标准通用标记语言下的一个子集)。HTTP用于实现 SOAP 的RPC 风格的传输, 而XML 是它的编码模式。
SOAP 通讯协议使用 HTTP 来发送XML 格式的信息。
soap将信息进行XML的序列化后,再用http协议的方式再打包进行传送,传送的方式还是tcp或者udp。
做个比喻就好理解了:tcp 和 udp 都是公路,暂且把tcp认为是一般公路,udp高速公路,soap和http就都是汽车,那么soap和http都可以在tcp和udp上跑。
说soap可以通过http来传送,实际就是说soap是小轿车,http是装轿车的卡车,把soap的信息装到http里面,然后再运输,当然走的道路还是tcp或udp。
说soap可以通过http协议来传输,这句话不太准确,比较准确第说法是:soap信息可以通过http协议包装后通过tcp或udp传输。
TCP相关知识
TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接,由于TCP是面向连接的所以只能用于端到端的通讯。
TCP提供的是一种可靠的数据流服务,采用“带重传的肯定确认”技术来实现传输的可靠性。TCP还采用一种称为“滑动窗口”的方式进行流量控制,所谓窗口实际表示接收能力,用以限制发送方的发送速度。
如果IP数据包中有已经封好的TCP数据包,那么IP将把它们向‘上’传送到TCP层。TCP将包排序并进行错误检查,同时实现虚电路间的连接。TCP数据包中包括序号和确认,所以未按照顺序收到的包可以被排序,而损坏的包可以被重传。
TCP将它的信息送到更高层的应用程序,例如Telnet的服务程序和客户程序。应用程序轮流将信息送回TCP层,TCP层便将它们向下传送到IP层,设备驱动程序和物理介质,最后到接收方。
面向连接的服务(例如Telnet、FTP、rlogin、X Windows和SMTP)需要高度的可靠性,所以它们使用了TCP。DNS在某些情况下使用TCP(发送和接收域名数据库),但使用UDP传送有关单个主机的信息。
IP
IP层接收由更低层(网络接口层例如以太网设备驱动程序)发来的数据包,并把该数据包发送到更高层—TCP或UDP层;相反,IP层也把从TCP或UDP层接收来的数据包传送到更低层。IP数据包是不可靠的,因为IP并没有做任何事情来确认数据包是否按顺序发送的或者有没有被破坏,IP数据包中含有发送它的主机的地址(源地址)和接收它的主机的地址(目的地址)。
高层的TCP和UDP服务在接收数据包时,通常假设包中的源地址是有效的。也可以这样说,IP地址形成了许多服务的认证基础,这些服务相信数据包是从一个有效的主机发送来的。IP确认包含一个选项,叫作IP source routing,可以用来指定一条源地址和目的地址之间的直接路径。对于一些TCP和UDP的服务来说,使用了该选项的IP包好像是从路径上的最后一个系统传递过来的,而不是来自于它的真实地点。这个选项是为了测试而存在的,说明了它可以被用来欺骗系统来进行平常是被禁止的连接。那么,许多依靠IP源地址做确认的服务将产生问题并且会被非法入侵。
socket通讯知识
先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。
服务端代码
#include
#include
#include
#include
#include
#include
#include #define SERVER_PORT 8888
#define QUEUE 20
int main( ){int socket_fd;struct sockaddr_in sock_server; struct sockaddr_in sock_client; int sockfd; int len &#61; 0;char buff[1024&#43;1];memset( &sock_server, 0x00, sizeof( sock_server ) );memset( &sock_client, 0x00, sizeof( sock_client ) );socket_fd &#61; socket( AF_INET, SOCK_STREAM, 0 );sock_server.sin_family&#61; AF_INET;sock_server.sin_port &#61; htons( SERVER_PORT );sock_server.sin_addr.s_addr &#61; htonl( INADDR_ANY );if( bind( socket_fd, (struct sockaddr *)&sock_server, sizeof( sock_server ) ) &#61;&#61; -1){perror( "bind error" ); exit(1);}printf( "bind success,port:%d\n", SERVER_PORT ); if( listen( socket_fd, QUEUE ) &#61;&#61; -1 ){perror( "listen error." );exit(1);} printf( "listen success.\n" ); while( 1 ){len &#61; sizeof( sock_client );sockfd &#61; accept( socket_fd, (struct sockaddr *)&sock_client, (socklen_t *)&len );if( sockfd < 0 ){continue;} printf( "accept() success.\n" );printf( "RECV:[%d],IP&#61;%s,PORT&#61;%d\n", sockfd, inet_ntoa(sock_client.sin_addr), ntohs(sock_client.sin_port) ); while( 1 ){memset( buff, 0x00, sizeof( buff ) ); if( recv( sockfd, buff, sizeof( buff )-1, 0 ) < 0 ){close( sockfd );printf( "recv error.\n" );break;}printf( "RECV FROM CLIENT:%s", buff ); if( !memcmp( buff, "exit", 4 ) ){close( sockfd );printf( "close sockfd\n" ); break;} fflush( stdin );memset( buff, 0x00, sizeof( buff ) );printf( "SERVER:" );memset( buff, 0x00, sizeof( buff ) );if( NULL &#61;&#61; ( fgets( buff, sizeof( buff )-1, stdin ) ) ){perror( "fgets error.\n" ); close( sockfd );fflush( stdin );break; }fflush( stdin );send( sockfd, buff, sizeof( buff )-1, 0 ); if( memcmp( buff, "exit", 4 ) &#61;&#61; 0 || memcmp( buff, "kill", 4 ) &#61;&#61; 0 ){close( sockfd );printf( "close client socket.\n" ); break;}}if( !memcmp( buff, "kill", 4 ) ){close( sockfd );printf( "close server socket.\n" );break;}}exit(0);
}
客户端代码
#include
#include
#include
#include
#include
#include
#include
#include #define SERVER_IP "192.168.137.10"
#define SERVER_PORT 8888int main( ){int sockfd;struct sockaddr_in serverAddr;int len &#61; 0;int iRet &#61; 0;char buff[128];memset( &serverAddr, 0x00, sizeof( serverAddr ) );memset( buff, 0x00, sizeof( buff ) );sockfd &#61; socket( AF_INET, SOCK_STREAM, 0 );if( sockfd < 0 ){printf( "socket() errror:%s", strerror( errno ) );exit(1);}serverAddr.sin_family &#61; AF_INET; serverAddr.sin_addr.s_addr &#61; inet_addr( SERVER_IP );serverAddr.sin_port &#61; htons( SERVER_PORT );len &#61; sizeof( serverAddr );iRet &#61; connect( sockfd, ( struct sockaddr *) &serverAddr, (socklen_t) len );if( iRet < 0 ){printf( "connect() error:%s", strerror(errno) );exit(1);}printf( "connect success.\n" );printf( "begin to communicate.\n" );while( 1 ){memset( buff, 0x00, sizeof( buff ) );printf( "CLIENT:" );fflush( stdin ); if( fgets( buff, sizeof( buff )-1, stdin ) &#61;&#61; NULL ){printf( "fgets() error.\n" );fflush( stdin );exit(1);}fflush( stdin ); iRet &#61; send( sockfd, buff, strlen(buff), 0 );if( iRet < 0 ){printf( "send() error:%s", strerror(errno) );exit(1);}if( !memcmp( buff, "exit", 4 ) ){printf( "close connection.\n" );close( sockfd );break;}memset( buff, 0x00, sizeof( buff ) );if( recv( sockfd, buff, sizeof(buff)-1, 0 ) < 0 ){printf( "recv error:%s", strerror( errno ) );close( sockfd );break;}printf( "RECV FROM SERVER:%s", buff );if( !memcmp( buff, "exit", 4 ) || !memcmp( buff, "kill", 4 ) ){printf( "close socket.\n" );close( sockfd );break;}}exit(0);
}