一个简单的客户端与服务器通讯

一个简单的客户端与服务器通讯
一个简单的客户端与服务器通讯

Linux网络编程-简单的客户端和服务器通讯程序开发入门(2)?007-09-19 21:15:32分类:燙/C++zieckey@https://www.360docs.net/doc/6c7303609.html,

简介:

本文详细介绍了Linux下B/S结构的客户端服务器通讯程序的开发入门,

其中对重要的网络函数和结构体作了详细的说明和分析,

最后给出一个简单的客户端和服务器通讯程序示例以加深理解。

2. 初等网络函数介绍(TCP)

Linux系统是通过提供套接字(socket)来进行网络编程的.网络程序通过socket和其它几个函数的调用,

会返回一个通讯的文件描述符,我们可以将这个描述符看成普通的文件的描述符来操作,

这就是linux的设备无关性的好处.我们可以通过向描述符读写操作实现网络之间的数据交流.

2.1 socket

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

domain:说明我们网络程序所在的主机采用的通讯协族(AF_UNIX和AF_INET等).?AF_UNIX只能够用于单一的Unix系统进程间通信,而AF_INET是针对Internet的,

因而可以允许在远程主机之间通信(当我们 man socket时发现 domain可选项是 PF_*而不是AF_*,

因为glibc是posix的实现所以用PF代替了AF,不过我们都可以使用的).

type:我们网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM等) SOCK_STREAM表明我们用的是TCP协议,

这样会提供按顺序的,可靠,双向,面向连接的比特流. SOCK_DGRAM 表明我们用的是UDP协议, 这样只会提供定长的,不可靠,无连接的通信.

protocol:由于我们指定了type,所以这个地方我们一般只要用0来代替就可以了 socket为网络通讯做基本的准备.

成功时返回文件描述符,失败时返回-1,看error可知道出错的详细情况.

2.2 bind

?一旦你有一个套接字,你可能要将套接字和机器上的一定的端口关联起来。(如果你想用listen()来侦听一定端口的

数据,这是必要一步)如果你只想用 connect(),那么这个步骤没有必要。但是无论如何,请继续读下去。

这里是系统调用 bind() 的大概:

int bind(int sockfd, struct sockaddr *my_addr, int addrlen)

sockfd:是由socket调用返回的文件描述符.

addrlen:是sockaddr结构的长度.

my_addr:是一个指向sockaddr的指针. 在中有 sockaddr的定义

struct sockaddr{

unisgned short as_family;

char sa_data[14];

};

不过由于系统的兼容性,我们一般不用这个头文件,而使用另外一个结构(struct sockaddr_in) 来代替.

在中有sockaddr_in的定义

struct sockaddr_in{

unsigned short sin_family;

unsigned short int sin_port;

struct in_addr sin_addr;

unsigned char sin_zero[8];

}

我们主要使用Internet所以sin_family一般为AF_INET,

sin_addr设置为INADDR_ANY表示可以和任何的主机通信,sin_port是我们要监听的端口号. sin_zero[8]是用来填充的. bind将本地的端口同socket返回的文件描述符捆绑在一起.

成功是返回0,失败的情况和socket一样

2.3 listen

牋牋牋牋牋牋牋牋牋牋牋?假如你不希望与远程的一个地址相连,或者说, 仅仅是将它踢开,那你就需要等待接入请求并

且用各种方法处理它们。处理过程分两步:首先,你听--listen(),然后,你接受--accept() (请看下面的内容)。

除了要一点解释外,系统调用 listen 也相当简单。

int listen(int sockfd, int backlog);

sockfd 是调用 socket() 返回的套接字文件描述符。backlog 是在进入队列中允许的连接数目。什么意思呢? 进入的连

接是在队列中一直等待直到你接受 (accept() 请看下面的文章)连接。它们的数目限制于队列的允许。大多数系统的允

许数目是20,你也可以设置为5到10。

和别的函数一样,在发生错误的时候返回-1,并设置全局错误变量 errno。

你可能想象到了,在你调用 listen() 前你或者要调用 bind() 或者让内核随便选择一个端口。如果你想侦听进入的连

接,那么系统调用的顺序可能是这样的:

socket();

?bind();

listen();

?/* accept() 应该在这 */

2.4 accept

?准备好了,系统调用 accept() 会有点古怪的地方的!你可以想象发生这样的事情:有人从很远的地方通过一个你在

侦听 (listen()) 的端口连接 (connect()) 到你的机器。它的连接将加入到等待接受(accept()) 的队列中。你调用

accept() 告诉它你有空闲的连接。它将返回一个新的套接字文件描述符!这样你就有两个套接字了,原来的一个还在侦

听你的那个端口, 新的在准备发送 (send()) 和接收 ( recv()) 数据。这就是这个过程! int accept(int sockfd, struct sockaddr *addr,int *addrlen)

sockfd:是listen后的文件描述符.

addr, addrlen是用来给客户端的程序填写的,服务器端只要传递指针就可以了.?bind,listen和accept是服务器端用的函数,

accept调用时,服务器端的程序会一直阻塞到有一个客户程序发出了连接.?accept成功时返回最后的服务器端的文件描述符,这个时候服务器端可以向该描述符写信息了. 失败时返回-1

2.5 connect

int connect(int sockfd, struct sockaddr * serv_addr,int addrlen)

sockfd:socket返回的文件描述符.

serv_addr:储存了服务器端的连接信息.其中sin_add是服务端的地址

addrlen:serv_addr的长度

connect函数是客户端用来同服务端连接的.成功时返回0,sockfd是同服务端通讯的文件描述符失败时返回-1.

牋?现在我们假设你是个 telnet 程序。你的用户命令你得到套接字的文件描述符。你听从命令调用了socket()。下一

步,你的用户告诉你通过端口 23(标准 telnet 端口)连接到"132.241.5.10"。你该怎么做呢? 幸运的是,你正在阅读

connect()--如何连接到远程主机这一章。你可不想让你的用户失望。

connect() 系统调用是这样的:

#include

#include

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

sockfd 是系统调用 socket() 返回的套接字文件描述符。serv_addr 是保存着目的地端口和 IP 地址的数据结构 struct

sockaddr。addrlen 设置为 sizeof(struct sockaddr)。

想知道得更多吗?让我们来看个例子:

#include

#include

#include

#define DEST_IP "132.241.5.10"

?#define DEST_PORT 23

main()

牋 {

int sockfd;

struct sockaddr_in dest_addr; /* 目的地址*/

sockfd = socket(AF_INET, SOCK_STREAM, 0); /* 错误检查 */

dest_addr.sin_family = AF_INET; /* host byte order */

dest_addr.sin_port = htons(DEST_PORT); /* short, network byte order */

dest_addr.sin_addr.s_addr = inet_addr(DEST_IP);

bzero(&(dest_addr.sin_zero),; /* zero the rest of the struct */

/* don't forget to error check the connect()! */

connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr));

牋 .

2.6重要的结构题介绍

首先是简单的一个:socket描述符。它是下面的类型:

int

仅仅是一个常见的 int。

从现在起,事情变得不可思议了,而你所需做的就是继续看下去。注意这样的事实:有两种字节排列顺序:重要的字节 (

有时叫 "octet",即八位位组) 在前面,或者不重要的字节在前面。前一种叫“网络字节顺序(Network Byte Order)

”。有些机器在内部是按照这个顺序储存数据,而另外一些则不然。当我说某数据必须按照NBO 顺序,那么你要调用函

数(例如 htons() )来将它从本机字节顺序 (Host Byte Order) 转换过来。如果我没有提到NBO, 那么就让它保持本机

字节顺序。

我的第一个结构(在这个技术手册TM中)--struct sockaddr.。这个结构为许多类型的套接字储存套接字地址信息:

struct sockaddr {

牋 unsigned short sa_family; /* 地址家族, AF_xxx */

牋 char sa_data[14]; /*14字节协议地址*/

牋 };

sa_family 能够是各种各样的类型,但是在这篇文章中都是 "AF_INET"。 sa_data包含套接字中的目标地址和端口信息。

这好像有点不明智。

为了处理struct sockaddr,程序员创造了一个并列的结构: struct sockaddr_in ("in" 代表 "Internet"。)

struct sockaddr_in {

牋 short int sin_family; /* 通信类型 */

牋 unsigned short int sin_port; /* 端口 */

牋 struct in_addr sin_addr; /* Internet 地址 */

牋 unsigned char sin_zero[8]; /* 与sockaddr结构的长度相同*/

牋 };

用这个数据结构可以轻松处理套接字地址的基本元素。注意 sin_zero (它被加入到这个结构,并且长度和 struct

sockaddr 一样) 应该使用函数 bzero() 或 memset() 来全部置零。同时,这一重要的字节,一个指向 sockaddr_in结构

体的指针也可以被指向结构体sockaddr并且代替它。这样的话即使 socket() 想要的是struct sockaddr *,你仍然可以

使用 struct sockaddr_in,并且在最后转换。同时,注意 sin_family 和 struct sockaddr 中的 sa_family 一致并能够

设置为 "AF_INET"。最后,sin_port和 sin_addr 必须是网络字节顺序 (Network Byte Order)!

你也许会反对道:"但是,怎么让整个数据结构 struct in_addr sin_addr 按照网络字节顺序呢?" 要知道这个问题的答

案,我们就要仔细的看一看这个数据结构: struct in_addr, 有这样一个联合 (unions): /* Internet 地址 (一个与历史有关的结构) */

牋 struct in_addr {

牋 unsigned long s_addr;

牋 };

它曾经是个最坏的联合,但是现在那些日子过去了。如果你声明 "ina" 是数据结构 struct sockaddr_in 的实例,那么

"ina.sin_addr.s_addr" 就储存4字节的 IP 地址(使用网络字节顺序)。如果你不幸的系统使用的还是恐怖的联合

struct in_addr ,你还是可以放心4字节的 IP地址并且和上面我说的一样(这是因为使用了“#define”。)

struct hostent结构体

这个数据结构是这样的:?牋爏truct hostent {?牋燾har *h_name;?牋燾har **h_aliases;?牋爄nt h_addrtype;?牋爄nt h_length;?牋燾har **h_addr_list;?牋爙;?牋 ?define h_addr h_addr_list[0] ?这里是这个数据结构的详细资料: ?struct hostent: ? h_name ? 地址的正式名称。? h_aliases ? 空字节-地址的预备名称的指针。? h_addrtype ?地址类型; 通常是AF_INET。 ? h_length ? 地址的比特长度。? h_addr_list ? 零字节-主机网络地址指针。网络字节顺序。? h_addr - h_addr_list中的第一地址。?

2.7本机转换

?我们现在到了新的章节。我们曾经讲了很多网络到本机字节顺序的转换,现在可以实践了! 你能够转换两种类型: short (两个字节)和 long (四个字节)。这个函数对于变量类型

unsigned 也适用。假设你想将

short 从本机字节顺序转换为网络字节顺序。用 "h" 表示 "本机 (host)",接着是 "to",然后用 "n" 表示 "网络

(network)",最后用 "s" 表示 "short": h-to-n-s, 或者 htons() ("Host to Network Short")。

太简单了...

如果不是太傻的话,你一定想到了由"n","h","s",和 "l"形成的正确组合,例如这里肯定没有stolh() ("Short to

Long Host") 函数,不仅在这里没有,所有场合都没有。但是这里有:

htons()--"Host to Network Short"

?htonl()--"Host to Network Long"

?ntohs()--"Network to Host Short"

?ntohl()--"Network to Host Long"

现在,你可能想你已经知道它们了。你也可能想:“如果我想改变 char 的顺序要怎么办呢?”但是你也许马上就想到,

“用不着考虑的”。你也许会想到:我的 68000 机器已经使用了网络字节顺序,我没有必要去调用 htonl() 转换 IP 地

址。你可能是对的,但是当你移植你的程序到别的机器上的时候,你的程序将失败。可移植性!这里是 Unix 世界!记

住:在你将数据放到网络上的时候,确信它们是网络字节顺序的。

最后一点:为什么在数据结构 struct sockaddr_in 中, sin_addr 和 sin_port 需要转换为网络字节顺序,而

sin_family 需不需要呢? 答案是: sin_addr 和 sin_port 分别封装在包的 IP 和 UDP 层。因此,它们必须要是网络字

节顺序。但是 sin_family 域只是被内核 (kernel) 使用来决定在数据结构中包含什么类型的地址,所以它必须是本机字

节顺序。同时, sin_family 没有发送到网络上,它们可以是本机字节顺序。

2.8 实例

服务器端程序

/******* 服务器程序 (server.c) ************/

/******************************************************************************* *************

**牋燦ame:server.c

**牋燯sed to study the network programming in Linux OS.

**牋燬howing how to use the functions,

** like socket,bind,listen,accept and write.

**牋燭his is the server program.

**牋燗uthor:zeickey

**牋燚ate:2006/9/16牋牋??**牋燙opyright (c) 2006,All Rights Reserved!

******************************************************************************** *************/

#include

#include

#include

#include

#include

#include

#include

#include

int main(int argc, char *argv[])

{

牋爄nt sockfd,new_fd;

牋爏truct sockaddr_in server_addr;

牋爏truct sockaddr_in client_addr;

牋爄nt sin_size,portnumber;

牋燾har hello[]="Hello! Are You Fine?\n";

牋 ?牋?if(argc!=2)

牋?{

牋?牋?fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]);

牋?牋?return 1;

牋?}

牋牋

牋?if( (portnumber = atoi(argv[1])) < 0 )

牋?{

牋?牋?fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]);

牋?牋?return 1;

牋?}

牋牋

牋?/* 服务器端开始建立socket描述符 */

牋?if( (sockfd = socket(AF_INET,SOCK_STREAM, 0)) == -1 )

牋?{

牋?牋?fprintf(stderr,"Socket error:%s\n\a",strerror(errno));

牋?牋?return 1;

牋?}

牋牋

牋?/* 服务器端填充 sockaddr结构 */

牋?//bzero(&server_addr, sizeof(struct sockaddr_in));

牋?memset(&server_addr, 0, sizeof(struct sockaddr_in));

牋?server_addr.sin_family = AF_INET;

牋?server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

牋?server_addr.sin_port = htons(portnumber);

牋牋

牋?/* 捆绑sockfd描述符,为下面的listen函数作准备 */

牋?if( bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1 )

牋?{

牋?牋?fprintf(stderr,"Bind error:%s\n\a",strerror(errno));

牋?牋?return 1;

牋?}

牋牋

牋?/* 监听sockfd描述符 */

牋?if( -1 == listen(sockfd,5) )

牋?{

牋?牋?fprintf(stderr,"Listen error:%s\n\a",strerror(errno));

牋?牋?return 1;

牋?}

牋牋

牋?while(1)

牋?{

牋?牋?/* 服务器阻塞,直到客户程序建立连接 */

牋?牋?sin_size=sizeof(struct sockaddr_in);

牋?牋?//if( (new_fd = accept(sockfd, (struct sockaddr *)(&client_addr), &sin_size)) == -1)

牋?牋?new_fd = accept(sockfd, (struct sockaddr *)(&client_addr), &sin_size); 牋?牋?if( -1 == new_fd )

牋?牋?{

牋?牋?牋?fprintf(stderr,"Accept error:%s\n\a",strerror(errno));

牋?牋?牋?return 1;

牋?牋?}

牋?牋牋

牋?牋?fprintf(stderr,"Server get connection from %s\n", inet_ntoa(client_addr.sin_addr));

牋?牋?if(write(new_fd,hello,strlen(hello))==-1)

牋?牋?{

牋?牋?牋?fprintf(stderr,"Write Error:%s\n",strerror(errno));

牋?牋?牋?return 1;

牋?牋?}

牋?牋?/* 这个通讯已经结束 */

牋?牋?close(new_fd);

牋?牋?/* 循环下一个 */

牋?}

牋?close(sockfd);

牋?return 0;

}

客户端程序

/******* 客户端程序 client.c ************/

/******************************************************************************* *************

**牋?Name:client.c

**牋?Used to study the network programming in Linux OS.

**牋?Showing how to use the functions,

** like socket,bind,listen,accept and write.

**牋?This is the client program.

**牋?Author:zeickey

**牋?Date:2006/9/16牋?牋牋

**牋?Copyright (c) 2006,All Rights Reserved!

******************************************************************************** *************/

#include

#include

#include

#include

#include

#include

#include

int main(int argc, char *argv[])

{

牋?int sockfd;

牋?char buffer[1024];

牋?struct sockaddr_in server_addr;

牋?//struct hostent *host;

牋?char *ip;

牋?int portnumber,nbytes;

牋牋

牋?if(argc!=3)

牋?{

牋?牋?fprintf(stderr,"Usage:%s ip portnumber\a\n",argv[0]);

牋?牋?return 1;

牋?}

牋牋

牋?//if((host=gethostbyname(argv[1]))==NULL)

牋?printf("agrv[1] = %s\n",argv[1]);

牋?if( strlen(ip=argv[1])< 7 )

牋?{

牋?牋?fprintf(stderr,"Get Ip address error\n");

牋?牋?return 1;

牋?}

牋牋

牋?if((portnumber=atoi(argv[2]))<0)

牋?{

牋?牋?fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]);

牋?牋?return 1;

牋?}

牋牋

牋?/* 客户程序开始建立 sockfd描述符 */

牋?if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)

牋?{

牋?牋?fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));

牋?牋?return 1;

牋?}

牋牋

牋?/* 客户程序填充服务端的资料 */

牋?bzero(&server_addr, sizeof(server_addr));

牋?server_addr.sin_family = AF_INET;

牋?server_addr.sin_port = htons(portnumber);

牋?//server_addr.sin_addr = *( (struct in_addr *)host->h_addr );

牋?//server_addr.sin_addr.s_addr = inet_addr(host->h_addr);

牋?server_addr.sin_addr.s_addr = inet_addr(ip);

牋?//server_addr.sin_addr.s_addr = ((struct in_addr*)(host->h_addr))->s_addr;

牋牋

牋?/* 客户程序发起连接请求 */

牋?if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)

牋?{

牋?牋?fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));

牋?牋?return 1;

牋?}

牋牋

牋?/* 连接成功了 */

牋?if((nbytes=read(sockfd,buffer,1024))==-1)

牋?{

牋?牋?fprintf(stderr,"Read Error:%s\n",strerror(errno));

牋?牋?return 1;

牋?}

牋?buffer[nbytes]='\0';

牋?printf("I have received:%s\n",buffer);

牋?/* 结束通讯 */

牋?close(sockfd);

牋?return 0;

}

MakeFile

这里我们使用GNU 的make实用程序来编译. 关于make的详细说明见 Make 使用介绍

######### Makefile ###########

all:server client

server:server.c

gcc $^ -o $@

client:client.c

gcc $^ -o $@

运行make后会产生两个程序server(服务器端)和client(客户端) 先运行./server portnumber& (portnumber随便取一个大于1204且不在/etc/services中出现的号码就用8888好了),然后运行 ./client localhost 8888 看看有什么结果. (你也可以用telnet和netstat试一试.) 上面是一个最简单的网络程序,不过是不是也有点烦.上面有许多函数我们还没有解释. 我会在下一章进行的详细的说明.

2.9 总结

总的来说网络程序是由两个部分组成的--客户端和服务器端.它们的建立步骤一般是:

服务器端

socket-->bind-->listen-->accept

客户端

socket-->connect

?

socket编程实现客户端和服务器端通信

#include "" #include <> #include #pragma comment(lib,"") #define BUF_SIZE 64 int _tmain(int argc,_TCHAR* argv[]) { WSADATA wsd; S OCKET sServer; S OCKET SClient; i nt retVal; c har buf[BUF_SIZE]; i f (WSAStartup(MAKEWORD(2,2),&wsd)!=0) {printf("wsastartup failed!\n"); return 1; } s Server=socket(AF_INET,SOCK_STREAM,IPPROTO_TC P); i f (INVALID_SOCKET==sServer) {printf("socket failed!\n"); WSACleanup(); return -1; } S OCKADDR_IN addrServ; =AF_INET; =htons(9990); retVal=bind(sServer,(const struct sockaddr*) &addrServ,sizeof(SOCKADDR_IN)); i f (SOCKET_ERROR==retVal) {printf("bind failed!\n"); closesocket(sServer); WSACleanup(); return -1; } retVal=listen(sServer,1); i f (SOCKET_ERROR==retVal) {printf("listen failed!\n"); closesocket(sServer); WSACleanup(); return -1; } p rintf("tcp server start...\n"); s ockaddr_in addrClient; i nt addrClientlen=sizeof(addrClient); S Client=accept(sServer,(sockaddr FAR*)&addrClient,&addrClientlen); i f (INVALID_SOCKET==SClient) { printf("accept failed!\n"); closesocket(sServer); WSACleanup(); return -1; } w hile(true) { ZeroMemory(buf,BUF_SIZE); retVal=recv(SClient,buf,BUF_SIZE,0); if (SOCKET_ERROR==retVal) { printf("recv failed!\n"); closesocket(sServer); closesocket(SClient); WSACleanup(); return -1; } SYSTEMTIME st; GetLocalTime(&st); char sDataTime[30]; sprintf(sDataTime,"%4d-%2d-%2d %2d:%2d:%2d",, ,,,,; printf("%s,recv from client [%s:%d]:%s\n",sDataTime,inet_ntoa,,buf); if (StrCmp(buf,"quit")==0) { retVal=send(SClient,"quit",strlen("quit"),0); break; } else { char msg[BUF_SIZE]; sprintf(msg,"message received -%s",buf); retVal=send(SClient,msg,strlen(msg),0); if (SOCKET_ERROR==retVal) { printf("send failed!\n"); closesocket(sServer); closesocket(SClient); WSACleanup(); return -1; } } } c losesocket(sServer); c losesocket(SClient);

关于客户端与数据库服务器端的时间同步问题

关于客户端与数据库服务器端的时间同步问题 这是一个做C/S的管理软件开发时经常被忽略的问题,客户端的时间与服务器的时间如果有偏差,数据统计、报表等等肯定会有“意外”的情况发生。 意图很简单:从数据库服务器获取到时间,根据这个时间修改当前客户端电脑时间。 用Sql的函数getdate(),是比较容易的。 我们是基于dotnet4.0、EntityFramework开发软件,所以希望用ESQL的方式获取数据库服务器的时间,但昨天折腾了半天,还没搞定。 如果有哪位同学已经解决了这个问题,希望能指点一下! 暂时解决,之所以说是暂时,是因为并没有用Esql的方式,而是用T-Sql的方式。 以下是我的过程: System.Data.EntityClient.EntityConnection 这个是实体概念模型与数据源的连接,继承自DbConnection 在这个连接下CreateCommand(),就需要写Esql语句,我的语句是"SELECT VALUE CurrentDateTime()",却是语法错误。翻遍了手册和网络查询,没有任何有用的结果。 但在这个连接对象下有一个属性StoreConnection,返回的是Sql方式的连接,在这个下面CreateCommand(),可以写T-Sql语句,我的语句是"SELECT getdate()",运行成功。

以上是程序代码例子: //与数据库服务器的时间进行同步 System.Data.EntityClient.EntityConnection conn = (System.D ata.EntityClient.EntityConnection)Blemployee.myData.Conne ction ; IDbConnection conn0=conn.StoreConnection; IDbCommand comm =conn0.CreateCommand(); //https://www.360docs.net/doc/6c7303609.html,mandText = "SELECT VALUE CurrentDateTime()"; https://www.360docs.net/doc/6c7303609.html,mandText = "SELECT getdate()"; https://www.360docs.net/doc/6c7303609.html,mandType = CommandType.Text; if (comm.Connection.State != ConnectionState.Open) comm.Connection.Open(); object tt= comm.ExecuteScalar(); DateTime sqlDT = Convert.ToDateTime(tt); SetLocalTime(sqlDT); //设置本机时间

服务器端与客户端建立并连接小Demo

服务器端代码: using https://www.360docs.net/doc/6c7303609.html,; using https://www.360docs.net/doc/6c7303609.html,.Sockets; Static void Main(string[] args){ Socket serverSocket=new Socket(AddressFamily.InterNetWork,SocketType.Stream,ProtocalTy pe.TCP); //new一个Socket对象,注意这里用的是流式Socket(针对于面向连接的TCP服务应用)而不是数据报式Socket(针对于面向无连接的UDP服务应用)。 IPAddress serverIP=IPAddress.Parse("127.0.0.1"); int port=2112; IPEndPoint ipEndPoint=new IPEndPoint(serverIP,port);//网络节点对象 serverSocket.Bind(ipEndPoint);//将结点绑定到套接字上 serverSocket.Listen(10);//设置连接队列的最大长度,可根据服务器的性能,可以设置更大程度。 Console.WriteLine("服务器已就绪准备客户端连接。。。。"); while(true){//循环监听端口,得到客户端连接 Socket socket=serverSocket.Accept();//当有客户端连接时,就产生一个socket实例 SessionServer sserver=new SessionServer(socket);//将socket实例传入到消息处理类中 Thread t=new Thread(sserver.GetClientMsg);//当有一个客户端连接,就启动一个线程来处理此客户端的消息 t.Start();

客户端与服务器端交互原理

客户端与服务器端交互原理 经常看到HTTP客户端与服务器端交互原理的各种版本的文章,但是专业术语太多,且流程过于复杂,不容易消化。于是就按照在Servlet 里面的内容大致做了一些穿插。本来连Tomcat容器和Servlet的生命周期也准备在这里一起写的,但怕过于庞大,于是就简单的引用了一些Servlet对象。这样的一个整个流程看下来,相信至少在理解HTTP协议和request和response是如何完成从请求到生成响应结果回发的。在后续的一些文章里会专门讲一讲Tomcat和Servlet 是如何处理请求和完成响应的,更多的是说明Servlet的生命周期。 HTTP介绍 1. HTTP是一种超文本传送协议(HyperText Transfer Protocol),是一套计算机在网络中通信的一种规则。在TCP/IP体系结构中,HTTP属于应用层协议,位于TCP/IP协议的顶层。 2. HTTP是一种无状态的协议,意思是指在Web浏览器(客户端)和Web 服务器之间不需要建立持久的连接。整个过程就是当一个客户端向服务器端发送一个请求(request),然后Web服务器返回一个响应(respo nse),之后连接就关闭了,在服务端此时是没有保留连接的信息。 3. HTTP遵循请求/响应(request/response)模型的,所有的通信交互都被构造在一套请求和响应模型中。 4. 浏览Web时,浏览器通过HTTP协议与Web服务器交换信息,Web服务器向Web 浏览器返回的文件都有与之相关的类型,这些信息类型的格式由 MIME 定义。 HTTP定义的事务处理由以下四步组成: 1. 建立连接。 2?客户端发送HTTP请求头。 3. 服务器端响应生成结果回发。 4. 服务器端关闭连接,客户端解析回发响应头,恢复页面。

实现基于TCP套接字的简单的服务器与客户端通信实验报告

计算机科学与技术系 实验(项目)报告 一、基本信息 二、目的与要求 目的: 通过实验掌握Linux环境下基于TCP套接字编程的基本步骤和方法。 要求: 1.掌握网络编程的基本框架; 2.了解客户端、服务器的基本概念; 3.掌握TCP套接字编程的基本流程及程序的调试方法。 三、完成实验(项目)过程和效果 内容: 1.程序结构设计; 2.程序数据设计; 3.程序基本流程; 4.编码、调试及运行。

server代码: client代码:

步骤: 1.程序结构设计 1)服务器端结构 先启动,进行socket、bind、listen、accept、一系列准备工作,然后如果没有建立连接,则服务器处于阻塞状态,等待客户端连接。 2)客户端结构。 客户端启动后,首先向服务器端发起建立连接的请求,得到同意后,连接建立成功,客户端和服务器端开始进行数据通信,客户机完成通信工程后释放链接,关闭套接字。

2.程序数据设计 1)服务器端相关数据: 监听套接字描述符、连接套接字描述符int sockfd,client_fd; 服务器端地址struct sockaddr_in my_addr 客户端地址struct sockaddr_in remote_addr 2)客户端相关数据 套接字描述符int sockfd; 服务器端地址结构struct sockaddr_in serv_addr; 保存接收到的数据char buf[MAXDATASIZE]; 接收的数据字符int recvbytes; 3.程序基本流程图。 四、知识应用以及经验总结 1.编写UDP通信程序?

客户机与服务器结构.

C/S 结构,即大家熟知的客户机和服务器结构。它是软件系统体系结构,通过它可以充分利用两端硬件环境的优势,将任务合理分配到Client端和Server端来实现,降低了系统的通讯开销。目前大多数应用软件系统都是Client/Server形式的两层结构,由于现在的软件应用系统正在向分布式的Web应用发展,Web和 Client/Server 应用都可以进行同样的业务处理,应用不同的模块共享逻辑组件;因此,内部的和外部的用户都可以访问新的和现有的应用系统,通过现有应用系统中的逻辑可以扩展出新的应用系统。这也就是目前应用系统的发展方向。概要(Client/Server或客户/服务器模式):Client和Server常常分别处在相距很远的两台计算机上,Client程序的任务是将用户的要求提交给Server程序,再将Server程序返回的结果以特定的形式显示给用户;Server程序的任务是接收客户程序提出的服务请求,进行相应的处理,再将结果返回给客户程序。传统的C/S体系结构虽然采用的是开放模式,但这只是系统开发一级的开放性,在特定的应用中无论是Client端还是Server端都还需要特定的软件支持。由于没能提供用户真正期望的开放环境,C/S结构的软件需要针对不同的操作系统开发不同版本的软件,加之产品的更新换代十分快,已经很难适应百台电脑以上局域网用户同时使用。而且代价高,效率低。编辑本段C/S工作模式C/S 结构的基本原则是将计算机应用任务分解成多个子任务,由多台计算机分工完成,即采用“功能分布”原则。客户端完成数据处理,数据表示以及用户接口功能;服务器端完成DBMS的核心功能。这种客户请求服务、服务器提供服务的处理方式是一种新型的计算机应用模式。编辑本段C/S结构的优点C/S结构的优点是能充分发挥客户端PC的处理能力,很多工作可以在客户端处理后再提交给服务器。对应的优点就是客户端响应速度快。缺点主要有以下几个:只适用于局域网。而随着互联网的飞速发展,移动办公和分布式办公越来越普及,这需要我们的系统具有扩展性。这种方式远程访问需要专门的技术,同时要对系统进行专门的设计来处理分布式的数据。客户端需要安装专用的客户端软件。首先涉及到安装的工作量,其次任何一台电脑出问题,如病毒、硬件损坏,都需要进行安装或维护。特别是有很多分部或专卖店的情况,不是工作量的问题,而是路程的问题。还有,系统软件升级时,每一台客户

服务器和客户端通信

实验六基于TCP/IP的网络编程 1 实验目的 MFC提供的关于网络应用的类CSocket是一个比较高级的封装,使用它编制出属于自己的网络应用程序,可以编一个属于自己的网络通讯软件。通过这个实验,同学们也可以增进对于TCP/IP协议的理解。 2 实验内容 基于TCP/IP的通信基本上都是利用SOCKET套接字进行数据通讯,程序一般分为服务器端和用户端两部分。设计思路(VC6.0下): 第一部分服务器端 一、创建服务器套接字(create)。 二、服务器套接字进行信息绑定(bind),并开始监听连接(listen)。 三、接受来自用户端的连接请求(accept)。 四、开始数据传输(send/receive)。 五、关闭套接字(closesocket)。 第二部分客户端 一、创建客户套接字(create)。 二、与远程服务器进行连接(connect),如被接受则创建接收进程。 三、开始数据传输(send/receive)。 四、关闭套接字(closesocket)。 CSocket的编程步骤:(注意我们一定要在创建MFC程序第二步的时候选上Windows Socket 选项,其中ServerSocket是服务器端用到的,ClientSocket是客户端用的。) (1)构造CSocket对象,如下例: CSocket ServerSocket; CSocket ClientSocket; (2)CSocket对象的Create函数用来创建Windows Socket,Create()函数会自行调用Bind()函数将此Socket绑定到指定的地址上面。如下例: ServerSocket.Create(823); //服务器端需要指定一个端口号,我们用823。ClientSocket.Create(); //客户端不用指定端口号。 (3)现在已经创建完基本的Socket对象了,现在我们来启动它,对于服务器端,我们需要这个Socket不停的监听是否有来自于网络上的连接请求,如下例: ServerSocket.Listen(5);//参数5是表示我们的待处理Socket队列中最多能有几个Socket。(4)对于客户端我们就要实行连接了,具体实现如下例: ClientSocket.Connect(CString SerAddress,Unsinged int SerPort);//其中SerAddress是服务器的IP地址,SerPort是端口号。 (5)服务器是怎么来接受这份连接的呢?它会进一步调用Accept(ReceiveSocket)来接收它,而此时服务器端还须建立一个新的CSocket对象,用它来和客户端进行交流。如下例:CSocket ReceiveSocket; ServerSocket.Accept(ReceiveSocket); (6)如果想在两个程序之间接收或发送信息,MFC也提供了相应的函数。 (7)代码 package test.socket3; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;

服务器与移动客户端通信设计

服务器与移动客户端通信设计 软件的通信方式是开发过程中的重要一环。智能手机的快速发展,使得手机不仅作为一般通讯工具,更进一步成为一款便携式移动互联网终端。通常来说,Android操作系统的手机使用Android系统自身集成的HttpClient直接访问网络资源[35]。 服务器MySQL 图4.7 客户端与数据库通信方式示意图 Fig.4.7 Communication mode between client and database HttpClient是一种HTTP协议的支撑工具包,它能够为客户端提供一系列高效、便捷、多功能的编程工具,且能够支持最新的HTTP协议,操作简单。对于HTTP连接中的各种复杂问题都能够予以有效的解决。如上图4.7所示,HttpClient 实现HTTP协议的方法,主要是GET与POST两种方法。 1.GET方法。HTTP协议的GET方法即利用HttpClient向客户端发送GET 请求,这一过程一般用来进行客户端的信息查询操作,例如,在本次客户端中, 其可以用于 检修故障信息、零部件信息以及检修工单信息的查询。具体的实现步骤有以下几 步[36]: 1) 创建HttpClient实例;2) 创建HttpPost实例。 3) 将需要发送的GET请求参数直接连接至URL地址中,并用“?”将参 数与地址隔开,每个参数之间用“&”隔开,若有需要额外添加的参数,可以选 择调用setParams()的方式来进行添加。 4) 调用第一步创建的HttpClient实例中的execute()方法来执行第二步创建 的HttpGet实例,并读取Response对象。 5) 采取调用getAllHeaders()、getHeaders(String name)等方式获取服务器响应,并释放连接,无论上述第四步的执行过程是否成功,都必须释放连接,允许 用户获得服务器的响应内容。 2.POST方法。HTTP协议的POST方法即利用HttpClient向客户端发送POST 请求,该请求过程一般用来进行客户端的信息修改操作,例如,在本课题所设计 的客户端中,其可以用于对登录、密码等修改等操作。其具体的实现过程也分为 五个步骤:

c#带界面-客户端与服务器通信TCP

服务器端界面 服务器端代码: using System; using System.Collections.Generic; using https://www.360docs.net/doc/6c7303609.html,ponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using https://www.360docs.net/doc/6c7303609.html,.Sockets; using System.Threading; using System.IO; using https://www.360docs.net/doc/6c7303609.html,; using System.Collections; namespace IMS.Server { public partial class Server : Form { TcpListener myListener; TcpClient tcpClient = new TcpClient(); Thread mythread; NetworkStream ns;

public Server() { InitializeComponent(); } private void Server_Load(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false; mythread = new Thread(new ThreadStart(receive)); mythread.IsBackground = true; mythread.Start(); } private void receive() { myListener = new TcpListener(IPAddress.Parse("192.168.1.106"), 8080); myListener.Start(); tcpClient = myListener.AcceptTcpClient(); while (true) { string rec = ""; ns = tcpClient.GetStream(); byte[] bytes = new byte[1024]; ns.Read(bytes,0,bytes.Length); rec = Encoding.Unicode.GetString(bytes); richTextBox1.Text = rec; ns.Flush(); } } private void btnSend_Click(object sender, EventArgs e) { try { ns = tcpClient.GetStream(); byte[] bytes = new byte[1024]; // bytes = Encoding.Unicode.GetBytes(sendmsg); bytes = Encoding.Unicode.GetBytes(richTextBox1.Text +"\r\n" + "服务器说:" + richTextBox2.Text);

Linux网络编程-简单的客户端和服务器通讯程序开发入门

Linux网络编程-基础知识(1) 1. Linux网络知识介绍 1.1 客户端程序和服务端程序 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 网络程序是先有服务器程序启动,等待客户端的程序运行并建立连接. 一般的来说是服务端的程序在一个端口上监听,直到有一个客户端的程序发来了请求. 1.2 常用的命令 由于网络程序是有两个部分组成,所以在调试的时候比较麻烦,为此我们有必要知道一些常用的网络命令 netstat 命令netstat是用来显示网络的连接,路由表和接口统计等网络的信息. netstat有许多的选项我们常用的选项是-an 用来显示详细的网络状态.至于其它的选项我们可以使用帮助手册获得详细的情况. telnet telnet是一个用来远程控制的程序,但是我们完全可以用这个程序来调试我们的服务端程序的. 比如我们的服务器程序在监听8888端口,我们可以用telnet localhost 8888来查看服务端的状况. 1.3 TCP/UDP介绍 TCP(Transfer Control Protocol)传输控制协议是一种面向连接的协议, 当我们的网络程序使用这个协议的时候,网络可以保证我们的客户端和服务端的连接是可靠的,安全的. UDP(User Datagram Protocol)用户数据报协议是一种非面向连接的协议, 这种协议并不能保证我们的网络程序的连接是可靠的,所以我们现在编写的程序一般是采用TCP协议的. Linux网络编程-简单的客户端和服务器通讯程序开发入门(2)简介: 本文详细介绍了Linux下B/S结构的客户端服务器通讯程序的开发入门, 其中对重要的网络函数和结构体作了详细的说明和分析, 最后给出一个简单的客户端和服务器通讯程序示例以加深理解。 2. 初等网络函数介绍(TCP) Linux系统是通过提供套接字(socket)来进行网络编程的.网络程序通过socket和其它几个函数的调用, 会返回一个通讯的文件描述符,我们可以将这个描述符看成普通的文件的描述符来操作, 这就是linux的设备无关性的好处.我们可以通过向描述符读写操作实现网络之间的数据交流. 2.1 socket

客户端与服务器通信

SimpleChatServer.java package test.chatclient; import java.io.*; import https://www.360docs.net/doc/6c7303609.html,.*; import java.util.*; public class SimpleChatServer { ArrayList clientOutputStreams; public static void main(String[] args){ new SimpleChatServer().go(); } public class ClientHandler implements Runnable{ BufferedReader reader; Socket sock; public ClientHandler(Socket clientSocket){ try{ sock = clientSocket; InputStreamReader isReader = new InputStreamReader(sock.getInputStream()); reader = new BufferedReader(isReader); }catch(Exception ex){ ex.printStackTrace(); } } @Override public void run() { String message; try{ while((message = reader.readLine()) != null){ System.out.println("read " + message); tellEveryone(message); } }catch(Exception ex){ ex.printStackTrace(); } } } public void tellEveryone(String message){ Iterator it = clientOutputStreams.iterator(); while(it.hasNext()){

java实现客户端与服务端之间的通信

import https://www.360docs.net/doc/6c7303609.html,.*; import java.io.*; import java.util.Calendar; import java.awt.*; import java.awt.event.*; class EchoClient extends Frame implements ActionListener,Runnable{ Thread t; static Calendar T; static int H; static int M; static int S; static String l; private Button b1 = new Button("发送"); private Button b2 = new Button("关闭"); private TextField t1 = new TextField(30); private TextArea t2 = new TextArea(); private int m; private String n; Socket connection; DataInputStream in; DataOutputStream out; private class window extends WindowAdapter{ public void windowClosing(WindowEvent e){ System.exit(0); } } private void focusEvt(java.awt.event.WindowEvent evt) { t1.requestFocus(); } public void clock(){ T=Calendar.getInstance(); H=T.get(Calendar.HOUR_OF_DAY); M=T.get(Calendar.MINUTE); S=T.get(Calendar.SECOND); l=String.valueOf(H)+":"+String.valueOf(M)+":"+String.valueOf(S); } public EchoClient(String i,int j){ super("客户端"); t = new Thread(this); m=j; n=i; t.start(); }

网络编程服务器与客户端编程

网络编程服务器与客户端编程2010-10-2915:50:08|分类:Linux下C语言| TCP编程的服务器端一般步骤是: 1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt();*可选 3、绑定IP地址、端口等信息到socket上,用函数bind(); 4、开启监听,用函数listen(); 5、接收客户端上来的连接,用函数accept(); 6、收发数据,用函数send()和recv(),者read()和write(); 7、关闭网络连接; 8、关闭监听; TCP编程的客户端一般步骤是: 1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt();*可选 3、绑定IP地址、端口等信息到socket上,用函数bind();*可选 4、设置要连接的对方的IP地址和端口等属性; 5、连接服务器,用函数connect(); 6、收发数据,用函数send()和recv(),或者read()和write(); 7、关闭网络连接; 与之对应的UDP编程步骤要简单许多,分别如下: UDP编程的服务器端一般步骤是: 1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt();*可选 3、绑定IP地址、端口等信息到socket上,用函数bind(); 4、循环接收数据,用函数recvfrom(); 5、关闭网络连接; UDP编程的客户端一般步骤是: 1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt();*可选 3、绑定IP地址、端口等信息到socket上,用函数bind();*可选 4、设置对方的IP地址和端口等属性;

客户端与服务器端的Socket通信

2009.17 网络与通信 NETWORK&COMMUNICATION 1引言 大部分网络协议的实现都由客户端(Client)和服务器端 (Server)来协作完成。这种模型本质上涉及两个不同的程序, 通常这两个程序在不同机器上运行。这些机器之间都有网络连接。服务器端程序提供服务并对来自客户程序的请求作成响应。而客户端程序则是在使用者和服务器端程序之间建立某种沟通的渠道,或者是作为使用服务器端提供的某种网络服务的工具。 一个典型的服务器与客户机之间的交互可能如下所示:(1)客户机提出一个请求; (2)服务器收到客户机的请求,进行分析处理;(3)服务器将运行处理的结果返回给客户机。 通常一个服务器需要向多个客户机提供服务。因此对服务器来说,还需要考虑如何有效地处理多个客户的请求。 2服务器与客户端的Socket 通信类型 Socket 的连接类型可以分为两种,分别是面向连接的字节 流类型(Sock_stream)和面向无连接数据报类型(Sock_dgram)。 面向无连接数据报类型的Socket 工作流程比较简单,双方不需要进行太多的沟通与交互。客户机直接将用户的请求打包发送到服务器端,省略了建立一个固定信息通道的过程。服务器端也是直接将处理的结果发送给客户端。其工作流程如图1所示。 面向连接的字节流类型的Socket 工作中有比较严格的操作次序,工作的原理也比较复杂。在这种类型的Socket 的工作过程中,必须首先启动服务器端,通过调用Socket ()函数建立一个Socket 对象,然后调用Bind ()函数将该Socket 对象和本地网络地址绑定到一起,再调用Listen ()函数使该Socket 对象处于侦听状态,并规定它的最大请求的数量。其工作流程如图2所示。 总的来说,无连接和面向连接的通信方式各有长处和短处。在仅仅涉及少量的信息传递的场合可以使用无连接操作;如果涉及大量信息传递的场合可以采用面向连接操作。 3Delphi 的Socket 组件 ClientSocket 组件为客户端组件。它是通信的请求方,也 就是说,它是主动地与服务器端建立连接。 客户端与服务器端的Socket 通信 夏 玲 摘 要:介绍有关Socket 通讯应用的基本知识,并通过客户端和服务器端的Delphi 编程实 例,说明两者是如何进行通信的。 关键词:Socket ;Delphi ;通信;客户端;服务器端 图1 无连接Socket 操作流程 图2 面向连接Socket 操作流程 49

Socket服务器与客户端双向通信实例

Socket服务器与客户端双向通信实例 using System; using System.Collections.Generic; using https://www.360docs.net/doc/6c7303609.html,ponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using https://www.360docs.net/doc/6c7303609.html,; using https://www.360docs.net/doc/6c7303609.html,.Sockets;//添加命名空间 using System.Threading;//添加命名空间 namespace WFAsynSocket { public partial class Form1 : Form { Thread LisThread;

Socket LisSocket; Socket newSocket; EndPoint point; string strmes = String.Empty; int port = 8000;//定义侦听端口号 public Form1() { InitializeComponent(); } private void btn_Listen_Click(object sender, EventArgs e) { LisThread = new Thread(new ThreadStart(BeginListern));//开线程执行BeginListern方法 LisThread.Start();//线程开始执行 } public IPAddress GetIP() { /*获取本地服务器的ip地址 */ IPHostEntry iep = Dns.GetHostEntry(Dns.GetHostName()); IPAddress ip = iep.AddressList[0]; return ip; } public void BeginListern() { LisSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, Proto colType.Tcp);//实例化Socket IPAddress ServerIp = GetIP();/*获取本地服务器的ip地址 */ IPEndPoint iep = new IPEndPoint(ServerIp, port); LisSocket.Bind(iep); /*将Socket绑定ip */ toolStripStatusLabel1.Text = iep.ToString() + "正在监听"; LisSocket.Listen(50); //Socket开始监听 newSocket = LisSocket.Accept();//获取连接请求的Socket /*接收客户端Socket所发的信息 */ while (true) { try {

Linux客户端服务器通信(2)

本文介绍了在Linux环境下的socket编程常用函数用法及socket编程的一般规则和客户/ 服务器模型的编程应注意的事项和常遇问题的解决方法,并举了具体代码实例。要理解 本文所谈的技术问题需要读者具有一定C语言的编程经验和TCP/IP方面的基本知识。要 实习本文的示例,需要 Linux下的gcc编译平台支持。 Socket定义 网络的Socket数据传输是一种特殊的I/O, Socket也是一种文件描述符。Socket 也具有一个类似于打开文件的函数调用—Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。常用的Socket类型有两种:流式Socket—SOCK_STREAM和数据报式 Socket—SOCK_DGRAM。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。 Socket编程相关数据类型定义 计算机数据存储有两种字节优先顺序:高位字节优先和低位字节优先。Intenet上数据以高位字节优先顺序在网络上传输,所以对于在内部是以低位字节优先方式存储数据的机器,在Internet上传输数据时就需要进行转换。 我们要讨论的第一个结构类型是:struct sockaddr,该类型是用来保存socket信息的: struct sockaddr { unsigned short sa_family; /* 地址族, AF_xxx */ char sa_data[14]; /* 14 字节的协议地址 */ }; sa_family一般为AF_INET;sa_data则包含该socket的IP地址和端口号。 另外还有一种结构类型: struct sockaddr_in { short int sin_family; /* 地址族 */ unsigned short int sin_port; /* 端口号 */ struct in_addr sin_addr; /* IP地址 */ unsigned char sin_zero[8]; /* 填充0 以保持与struct sockaddr同样大 小 */ }; 这个结构使用更为方便。sin_zero(它用来将sockaddr_in结构填充到与 struct sockaddr同样的长度)应该用bzero ()或memset()函数将其置为零。指向 sockaddr_in 的指针和指向sockaddr的指针可以相互转换,这意味着如果一个函数所需参数类型是sockaddr时,你可以在函数调用的时候将一个指向sockaddr_in的指针转换为 指向sockaddr的指针;或者相反。 sin_family通常被赋AF_INET;in_port和sin_addr应该转换成为网络字节优先顺序;而sin_addr则不需要转换。 我们下面讨论几个字节顺序转换函数:

Android手机客户端与Web服务器的通信

1.Android手机访问Web服务器 大多数中间件技术开发人员熟悉如何用计算机浏览器访问互联网,浏览器的主要作用是给互联网的Web服务器提交数据、验证数据和解析显示数据。其工作原理是通过Http协议.提交数据用GET或者POST方法,客户端的数据通过浏览器网页提交给web应用服务器,应用服务器通过Web页面接收各种不同类型数据,将数据通过服务器的Servlet子类Http Servlet对象提交给服务器端处理逻辑.服务器逻辑将接收到的数据按照客户端的要求在Web服务器端进行运算,再将运算的结果返回给客户端浏览器进行解析和显示。这里关键是Web服务器端的Servlet.它是服务器和客户端交互据的服务器端端口,即所有客户端的数据都要通过Servlet提交给Web服务器.所有要返回给客户端的数据都要通过Web服务器端的Servlet响应给客户端。在实际应用的服务器端,创建Servlet的子类对象HttpServlet (HttpServletRequest和 HttpServletResponse),分别用来接收客户端的数据和将数据返回给客户端。现在的问题就在Android手机终端.如何能够把客户的数据通过手机界面提交给Web服务器? Android 手机终端访问Web服务器的技术架构是怎样的?又如何能够在手机终端把web服务器响应的数据按照服务器的不同数据类型恢复原型?这就是下面要解决的问题。 1.1 手机客户端向Web应用服务器发送请求信息 以实际开发的Android手机终端登录功能为案例介绍如何利用Sun公

司提供的 java 数据流和过滤流结合Android提供的API提取Web服务器端不同类型的数据。 1) 首先引用所需要的各种API在Android手机终端开发应用程序时.首先需要利用Google和Sun公司提供的必要类包(API),包括http 通信协议类org.apache.http,*消息类org.apache.http.Message.*数据流类java.io.*android.app.Activity等。 2)定义访问网站的URL 3)创建Android程序界面类创建一个手机界面,需要继承Android提供的Activity,在该类中创建提交给Web服务器的数据的 H ttpPost 对象。覆盖Activity类的方法on—Create(Bundle b),创建事件监听器OnClickListener对象,在其中实现 onClick(View v)方法,再把该事件监听器注册到相应的事件源 loginB utton上。 4)创建HttpPost对象HttpPost对象的主要作用是将Android手机端的数据提交给Web应用服务器,为此Android提供了很好的AP I.这里就利用Android和Sun公司提供的这些类把需要提交给服务器的数据(NameValuePair对象)保存到一个List对象中。 5 )设置数据编码方式Android手机在将准备好的数据发送到Web服务器之前,需要对数据的编码进行规定,这样服务器在接收到这些数据后,就会根据发送过去的文字编码处理和显示。 6 ) 提交HttpPost对象和获取服务器HttpResponse响应数据完成

相关文档
最新文档