Winsocket入门教程二:非阻塞式服务器和客户端程序(TCP)

上次为大家介绍了阻塞式多线程服务端程序和阻塞式客户端程序的设计方法,但是在上文的最后也提到过,服务器程序会因为建立连接和关闭连接而频繁的创建和关闭线程会产生大量的内存碎片,从而导致服务端程序不能保证长时间的稳定运行。因此我在这里为大家介绍另外一种建立服务器和客户端程序的方法,即建立非阻塞式的服务器和客户端程序。

那什么是非阻塞呢?非阻塞是相对于阻塞而言,阻塞指的是在进行一个操作的时候,如服务器接收客户端的连接(accept),服务器或者客户端读写数据(read、write),如果该操作没有执行完成(成功或者失败都算是执行完成),则程序会一直阻塞在操作执行的地方,直到该操作返回一个明确的结果。而非阻塞式程序则不一样,非阻塞式程序会在产生阻塞操作的地方阻塞一定的时间(该时间可以由程序员自己设置)。如果操作没有完成,在到达所设置的时间之后,无论该操作成功与否,都结束该操作而执行程序下面的操作。

为了执行非阻塞操作,我们在创建了一个套接口后,需要将套接口设置为非阻塞的套接口。为了将套接口设置成为非阻塞套接口,我们需要调用ioctlsocket函数将套接口设置为非阻塞的套接口。ioctlsocket函数的定义如下:

int ioctlsocket( SOCKET s, long cmd, u_long FAR *argp)

该函数的作用是控制套接口的I/O模式。

参数s表示要设置的套接口;参数cmd表示要对该套接口设置的命令,为了要将套接口设置成为非阻塞的,我们应该填写FIONBIO;argp表示填写命令的值,如我们要将套接口设置成非阻塞的,我们需要将值设置成为1,如果我们要将套接口设置成为非阻塞状态的话,我们将值设置成为0就是了。

为了进行非阻塞的操作,我们需要在进行操作之前调用select函数,select函数的定义如下:

int select(int nfds, fd_set FAR *readfds, fd_set FAR *writefds,

fd_set FAR *exceptfds,

const struct timeval FAR *timeout);

该函数设定一个或多个套接口的状态,并进行必要的等待,以便执行异步I/0(非阻塞)操作。

参数nfds被忽略,该参数的作用仅仅是为了与伯克利套接口相兼容;参数readfd s表示要检测的可读套接口的集合(该参数可选,可为设置

为NULL);参数readfds表示要检测的可写套接口的集合(该参数可选,可为设置为NUL L);参数exceptfds表示要检测的套接口的错误(该参数可选,可为设置为NULL);参数t imeout表示执行该函数时需要等待的时间,如果为NULL则表示阻塞操作,为0则表示立即返回。

下面让我们来看看参数类型fd_set,fd_set表示套接字的集合。在使用select函数时,我们需要将相应的套接字加入到相应的集合中。如果集合中的套接字有信号,select 函数的返回值即为集合中有信号的套接字数量。

我们用下面的几个宏来操作fd_set集合。我们可以使用FD_SET(s, *set)将套接字s加入到集合set中;我们可以使用FD_CLR(s, *set)将套接字s移除出集合set;我们可以使用FD_ZERO(*set)将集合set清空;最后,我们可以使用FD_ISSET(s, *set)来判断套接字s是否在集合中有信号。

接下来再让我们来看看select函数的三个集合参数readfds、writefds以及except fds。

readfds表示可读套接字的集合,可读套接字在三种情况下有信号出现:一、如果集合中有套接字处于监听状态,并且该套接字上有来自客户端的连接请求;二、如果集合中的套接字收到了send操作发送过来的数据;三、如果集合中的套接字被关闭、重置或者中断。

writefds表示可写套接字的集合,可写套接字在两种情况下有信号出现:一、集合中的套接字经过connect操作后,连接成功;二、可以用send操作向集合中的套接字写数据。

exceptfds表示错误套接字的集合,错误套接字在两种情况下有信号出现:一、集合

中的套接字经过connect操作后,连接失败;二、有带外数据到来。

在我们了解了创建服务器和客户端程序的基础知识后,我们再来看看示例程序,以加深我们对知识的理解。

程序的运行结果如下所示:

下面是服务器程序的代码:

view plaincopy to clipboardprint?

1.#include

2.#include

3.#include

4.#include

5.#pragma comment(lib, "ws2_32.lib")

6.#define ASSERT assert

https://www.360docs.net/doc/c43928717.html,ing std::cin;

https://www.360docs.net/doc/c43928717.html,ing std::cout;

https://www.360docs.net/doc/c43928717.html,ing std::endl;

https://www.360docs.net/doc/c43928717.html,ing std::list;

11.typedef list SocketList;

12.typedef list::iterator SocketListIterator;

13.static const int c_iPort = 10001;

14.bool GraceClose(SOCKET *ps);

15.int main()

16.{

17.int iRet = SOCKET_ERROR;

18. // 初始化Winsocket,所有Winsocket程序必须先使用WSAStartup

进行初始化

19. WSADATA data;

20. ZeroMemory(&data, sizeof(WSADATA));

21. iRet = WSAStartup(MAKEWORD(2, 0), &data);

22. ASSERT(SOCKET_ERROR != iRet);

23. // 建立服务端程序的监听套接字

24. SOCKET skListen = INVALID_SOCKET;

25. skListen = socket(AF_INET, SOCK_STREAM, 0);

26. ASSERT(INVALID_SOCKET != skListen);

27. // 初始化监听套接字地址信息

28. sockaddr_in adrServ; // 表示网络地址

29. ZeroMemory(&adrServ, sizeof(sockaddr_in));

30. adrServ.sin_family = AF_INET; // 初始化地址格式,只能

为AF_INET

31. adrServ.sin_port = htons(c_iPort); // 初始化端口,由于网络

字节顺序和主机字节顺序相反,所以必须使用htons将主机字节顺序转换成网络字节顺序

32. adrServ.sin_addr.s_addr = INADDR_ANY; // 初始化IP,由于

是服务器程序,所以可以将INADDR_ANY赋给该字段,表示任意的IP

33. // 绑定监听套接字到本地

34. iRet = bind(skListen, (sockaddr*)&adrServ, sizeof(sockaddr_

in));

35. ASSERT(SOCKET_ERROR != iRet);

36. // 使用监听套接字进行监听

37. iRet = listen(skListen, FD_SETSIZE); // SOMAXCONN表示可以

连接到该程序的最大连接数

38. ASSERT(SOCKET_ERROR != iRet);

39. cout << "Server began listening..." << endl;

40. // 将套接口从阻塞状态设置到费阻塞状态

41. unsigned long ulEnable = 1;

42. iRet = ioctlsocket(skListen, FIONBIO, &ulEnable);

43. ASSERT(SOCKET_ERROR != iRet);

44. fd_set fsListen;

45. FD_ZERO(&fsListen);

46. fd_set fsRead;

47. FD_ZERO(&fsRead);

48. timeval tv;

49. https://www.360docs.net/doc/c43928717.html,_sec = 1;

50. https://www.360docs.net/doc/c43928717.html,_usec = 0;

51. SocketList sl;

52. for(;;)

53. {

54. // 接收来自客户端的连接, 并将新建的套接字加入

55. // 套接字列表中

56. FD_SET(skListen, &fsListen);

57. iRet = select(1, &fsListen, NULL, NULL, &tv);

58. if(iRet > 0)

59. {

60. sockaddr_in adrClt;

61.int iLen = sizeof(sockaddr_in);

62. ZeroMemory(&adrClt, iLen);

63. SOCKET s = accept(skListen, (sockaddr*)&adrClt,&iLen);

64. ASSERT(INVALID_SOCKET != s);

65. sl.push_back(s);

66. cout << "Server accepted a connection. The socket i

s " << s << endl;

67. }

68. // 将套接字列表中的套接字加入到可读套接字集合中

69. // 以便在可以检测集合中的套接字是否有数据可读

70. FD_ZERO(&fsRead);

71. for(SocketListIterator iter = sl.begin(); iter != sl.end(); ++

iter)

72. {

73. FD_SET(*iter, &fsRead);

74. }

75. // 检测集合中的套接字是否有数据可读

76. iRet = select(sl.size(), &fsRead, NULL, NULL, &tv);

77. if(iRet > 0)

78. {

79. for(SocketListIterator iter = sl.begin(); iter != sl.end

(); ++iter)

80. {

81. // 如果有数据可读, 则遍历套接字列表中的所有套接字

82. // 检测出有数据可读的套接字

83. iRet = FD_ISSET(*iter, &fsRead);

84. if(iRet > 0)

85. {

86. // 读取套接字上的数据

87. const int c_iBufLen = 512;

88.char szBuf[c_iBufLen + 1] = {'\0'};

89.int iRead = SOCKET_ERROR;

90. iRead = recv(*iter, szBuf, c_iBufLen, 0);

91. if (0 >= iRead)// 读取出现错误或者对方关闭连接

92. {

93. iRead == 0 ? cout << "Connection shutdown at s

ocket " << *iter << endl :

94. cout << "Connection recv error at socket " <

< *iter << endl;

95. iRet = GraceClose(&(*iter));// 如果出错则关闭套接字

96. ASSERT(iRet);

97. }

98. else

99. {

100. szBuf[iRead] = '\0';

101. cout << "Server recved message from socket " < < *iter << ": " << szBuf << endl;

102. // 创建可写集合

103. FD_SET fsWrite;

104. FD_ZERO(&fsWrite);

105. FD_SET(*iter, &fsWrite);

106. // 如果有数据可写, 则向客户端发送数据

107. iRet = select(1, NULL, &fsWrite, NULL, &tv); 108. if (0 < iRet)

109. {

110.int iWrite = SOCKET_ERROR;

111. iWrite = send(*iter, szBuf, iRead, 0);

112. if (SOCKET_ERROR == iWrite)

113. {

114. cout << "Send message error at socket " < < *iter << endl;

115. iRet = GraceClose(&(*iter));

116. ASSERT(iRet);

117. }

118. }

119. }

120. }

121. }

122. sl.remove(INVALID_SOCKET); // 删除无效的套接字, 套接字在关闭后被设置为无效

123. }

124. }

125. // 将套接字设置回阻塞状态

126. ulEnable = 0;

127. iRet = ioctlsocket(skListen, FIONBIO, &ulEnable); 128. ASSERT(SOCKET_ERROR != iRet);

129. // 关闭监听套接字

130. iRet = GraceClose(&skListen);

131. ASSERT(iRet);

132. // 清理Winsocket资源

133. iRet = WSACleanup();

134. ASSERT(SOCKET_ERROR != iRet);

135. system("pause");

136. return 0;

137.}

138.bool GraceClose(SOCKET *ps)

139.{

140. const int c_iBufLen = 512;

141.char szBuf[c_iBufLen + 1] = {'\0'};

142. // 关闭该套接字的连接

143.int iRet = shutdown(*ps, SD_SEND);

144. while(recv(*ps, szBuf, c_iBufLen, 0) > 0);

145. if (SOCKET_ERROR == iRet)

146. {

147. return false;

148. }

149. // 清理该套接字的资源

150. iRet = closesocket(*ps);

151. if (SOCKET_ERROR == iRet)

152. {

https://www.360docs.net/doc/c43928717.html,ing std::cout;

https://www.360docs.net/doc/c43928717.html,ing std::endl;

9.static const char c_szIP[] = "127.0.0.1";

10.static const int c_iPort = 10001;

11.bool GraceClose(SOCKET *ps);

12.int main()

13.{

14.int iRet = SOCKET_ERROR;

15. // 初始化Winsocket,所有Winsocket程序必须先使用WSAStartup进行初

始化

16. WSADATA data;

17. ZeroMemory(&data, sizeof(WSADATA));

18. iRet = WSAStartup(MAKEWORD(2, 0), &data);

19. ASSERT(SOCKET_ERROR != iRet);

20. // 建立连接套接字

21. SOCKET skClient = INVALID_SOCKET;

22. skClient = socket(AF_INET, SOCK_STREAM, 0);

23. ASSERT(INVALID_SOCKET != skClient);

24. // 初始化连接套接字地址信息

25. sockaddr_in adrServ; // 表示网络地址

26. ZeroMemory(&adrServ, sizeof(sockaddr_in));

27. adrServ.sin_family = AF_INET; // 初始化地址格式,只能为

AF_INET

28. adrServ.sin_port = htons(c_iPort); // 初始化端口,由于网络字

节顺序和主机字节顺序相反,所以必须使用htons将主机字节顺序转换成网络字节顺序

29. adrServ.sin_addr.s_addr = inet_addr(c_szIP); // 初始化IP,由于网

络字节顺序和主机字节顺序相反,所以必须使用inet_addr将主机字节顺序转换成网络字节顺序

30. // 将套接口从阻塞状态设置到非阻塞状态

31. unsigned long ulEnable = 1;

32. iRet = ioctlsocket(skClient, FIONBIO, &ulEnable);

33. ASSERT(SOCKET_ERROR != iRet);

34. fd_set fsWrite;

35. TIMEVAL tv;

36. https://www.360docs.net/doc/c43928717.html,_sec = 1;

37. https://www.360docs.net/doc/c43928717.html,_usec = 0;

38. cout << "Client began to connect to the server..." << endl;

39. for (;;)

40. {

41. // 使用非阻塞方式连接服务器,请注意connect操作的返回值总是为SOC

KET_ERROR

42. iRet = connect(skClient, (sockaddr*)&adrServ, sizeof(sockaddr_i

n));

43.int iErrorNo = SOCKET_ERROR;

44.int iLen = sizeof(int);

45. // 如果getsockopt返回值不为0,则说明有错误出现

46. if (SOCKET_ERROR == iRet && 0 != getsockopt(skClient, SOL_S

OCKET, SO_ERROR, (char*)&iErrorNo, &iLen))

47. {

48. cout << "An error happened on connecting to server. The erro

r no is " << iErrorNo

49. << ". The program will exit now." << endl;

50. exit(-1);

51. }

52.

53. FD_ZERO(&fsWrite);

54. FD_SET(skClient, &fsWrite);

55. // 如果集合fsWrite中的套接字有信号,则说明连接成功,此时iRet的返回

值大于0

56. iRet = select(1, NULL, &fsWrite, NULL, &tv);

57. if (0 < iRet)

58. {

59. cout << "Successed connect to the server..." << endl;

60. break;

61. }

62. }

63. for(;;)

64. {

65. const int c_iBufLen =512;

66.char szBuf[c_iBufLen + 1] = {'\0'};

67. cout << "what you will say:";

68. cin >> szBuf;

69. if(0 == strcmp("exit", szBuf))

70. {

71. break;

72. }

73. FD_ZERO(&fsWrite);

74. FD_SET(skClient, &fsWrite);

75. // 如果集合fsWrite中的套接字有信号, 则可以用send操作写数据

76. iRet = select(1, NULL, &fsWrite, NULL, &tv);

77. if (0 < iRet)

78. {

79. iRet = send(skClient, szBuf, strlen(szBuf), 0);

80. if(SOCKET_ERROR == iRet)

81. {

82. cout << "send error." << endl;

83. break;

84. }

85. fd_set fsRead;

86. FD_ZERO(&fsRead);

87. FD_SET(skClient, &fsRead);

88. // 如果集合fsRead中的套接字有信号, 则可以用recv操作写数据

89. iRet = select(1, &fsRead, NULL, NULL, &tv);

90. if (0 < iRet)

91. {

92. iRet = recv(skClient, szBuf, c_iBufLen, 0);

93. if(0 == iRet)

94. {

95. cout << "connection shutdown." << endl;

96. break;

97. }

98. else if(SOCKET_ERROR == iRet)

99. {

100. cout << "recv error." << endl;

101. break;

102. }

103. szBuf[iRet] = '\0';

104. cout << szBuf << endl;

105. }

106. }

107. }

108. // 将套接字设置回阻塞状态

109. ulEnable = 0;

110. iRet = ioctlsocket(skClient, FIONBIO, &ulEnable);

111. ASSERT(SOCKET_ERROR != iRet);

112. // 关闭监听套接字

113. iRet = GraceClose(&skClient);

114. ASSERT(iRet);

115. // 清理Winsocket资源

116. iRet = WSACleanup();

117. ASSERT(SOCKET_ERROR != iRet);

118. system("pause");

119. return 0;

120.}

121.bool GraceClose(SOCKET *ps)

122.{

123. const int c_iBufLen = 512;

124.char szBuf[c_iBufLen + 1] = {'\0'}; 125. // 关闭该套接字的连接

126.int iRet = shutdown(*ps, SD_SEND); 127. while(recv(*ps, szBuf, c_iBufLen, 0) > 0); 128. if (SOCKET_ERROR == iRet)

129. {

130. return false;

131. }

132. // 清理该套接字的资源

133. iRet = closesocket(*ps);

134. if (SOCKET_ERROR == iRet)

135. {

136. return false;

137. }

138. *ps = INVALID_SOCKET;

139. return true;

140.}

Android开发规范参考文档

Android开发参考文档 一、Android编码规范 1. java代码中不出现中文,最多注释中可以出现中文.xml代码中注释 2. 成员变量,局部变量、静态成员变量命名、常量(宏)命名 1). 成员变量: activity中的成员变量以m开头,后面的单词首字母大写(如Button mBackButton; String mName);实体类和自定义View的成员变量可以不以m开头(如ImageView imageView,String name), 2). 局部变量命名:只能包含字母,组合变量单词首字母出第一个外,都为大写,其他字母都为小写 3). 常量(宏)命名: 只能包含字母和_,字母全部大写,单词之间用_隔开UMENG_APP_KEY 3. Application命名 项目名称+App,如SlimApp,里面可以存放全局变量,但是杜绝存放过大的实体对象4. activity和其中的view变量命名 activity命名模式为:逻辑名称+Activity view命名模式为:逻辑名称+View 建议:如果layout文件很复杂,建议将layout分成多个模块,每个模块定义一个moduleViewHolder,其成员变量包含所属view 5. layout及其id命名规则 layout命名模式:activity_逻辑名称,或者把对应的activity的名字用“_”把单词分开。

命名模式为:view缩写_模块名称_view的逻辑名称, 用单词首字母进行缩写 view的缩写详情如下 LayoutView:lv RelativeView:rv TextView:tv ImageView:iv ImageButton:ib Button:btn 6. strings.xml中的 1). id命名模式: activity名称_功能模块名称_逻辑名称/activity名称_逻辑名称/common_逻辑名称,strings.xml中,使用activity名称注释,将文件内容区分开来 2). strings.xml中使用%1$s实现字符串的通配,合起来写 7. drawable中的图片命名 命名模式:activity名称_逻辑名称/common_逻辑名称/ic_逻辑名称 (逻辑名称: 这是一个什么样的图片,展示功能是什么) 8. styles.xml 将layout中不断重现的style提炼出通用的style通用组件,放到styles.xml中; 9. 使用layer-list和selector,主要是View onCclick onTouch等事件界面反映

安装手册

联网单位备案巡查系统(WEB)项目 安装手册 编写: 审核: 批准: ?北京锐安科技有限公司 北京海淀区中关村南大街乙56号方圆大厦9层100044 电话:(010)58719666 传真:(010) 58719666-9588 服务电话:(010) 58719666

变更记录 *变化状态:C――创建,A——增加,M——修改,D——删除 修改点说明:对变化状态进行简单解释,如增加了某项功能,修改了某个模块等信息。 版本未通过评审前,版本号从V0.X开始,第一次评审通过后变为V1.0 版本号变化状态修改点说明变更人存放位置审批人审批日期

目录 1. 引言 (4) 1.1. 编写目的 (4) 1.2. 范围 (4) 2. 安装条件 (4) 2.1. 典型部署拓扑图 (4) 2.2. 软件环境和配置要求 (5) 3. 安装步骤和配置方法简介 (6) 4. 安装步骤 (7) 4.1. 缓冲软件安装步骤 (7) 4.2. 数据库软件安装步骤 (9) 4.3. Web系统安装步骤 (10) 4.4. 爬虫软件安装步骤 (11) 5. 卸载步骤 (13) 5.1. 缓冲软件卸载 (13) 5.2. 数据库卸载 (13) 5.3. web软件卸载 (13) 5.4. 爬虫软件卸载 (14)

1.引言 1.1. 编写目的 本手册是给实施人员或者用户的系统安装人员提供联网单位备案巡查系统(WEB)安装和配置指导,帮助实施人员或用户能够快速安装配置联网单位备案巡查系统(WEB)。 1.2. 范围 本手册描述了联网单位备案巡查系统(WEB)所需的硬件和软件环境以及软件安装的条件、方法、步骤和注意事项等内容。 2.安装条件 2.1. 典型部署拓扑图 2.2. 软件环境和配置要求 操作系统:CentOS 6.4 64bits

lab1 SQLPlus使用及简单Select语句

实验1 SQL*Plus使用及简单Select语句 实验人:_________ 学号_____ 班级____________ 实验目的: 1.掌握SQL*Plus常用功能的使用。 2.掌握简单查询的语法。 实验平台: 1.Windows 2000/XP。 2.Oracle 10g 实验过程记录及分析: 1.SQL*Plus的使用: 1) 2) 3)如果某个用户连接数据库时,发生了“协议适配器错误”,分析其原因,并给出解决错 4)

5) 6) 7) 2. SQL 1) 2)3

4)查询emp表中,工资额大于2000的员工的姓名及其工资额。 5) 6) 7)查询emp表中,ename列含有字母A的员工的姓名。

8) 9) 10

11)使用to_date函数查询1981年入职的员工姓名。 SQL> select * from emp 2 where to_char(hiredate,'yyyy')='1981'; EMPNO ENAME JOB MGR HIREDATE SAL COMM ---------- ---------- --------- ---------- -------------- ---------- ---------- DEPTNO ---------- 7499 ALLEN SALESMAN 7698 20-2月 -81 1600 300 30 7521 WARD SALESMAN 7698 22-2月 -81 1250 500 30 7566 JONES MANAGER 7839 02-4月 -81 2975 20 EMPNO ENAME JOB MGR HIREDATE SAL COMM ---------- ---------- --------- ---------- -------------- ---------- ---------- DEPTNO ---------- 7654 MARTIN SALESMAN 7698 28-9月 -81 1250 1400 30 7698 BLAKE MANAGER 7839 01-5月 -81 2850 30 7844 TURNER SALESMAN 7698 08-9月 -81 1500 0 30 EMPNO ENAME JOB MGR HIREDATE SAL COMM ---------- ---------- --------- ---------- -------------- ---------- ----------

android中selector背景选择器(全部属性)

浅谈android的selector背景选择器 ---------------------------------------------------- Item顺序是有讲究的,条件限定越细致,则应该放到前面。比如这儿如果把1,2行和3,4行的item交换,那么pressed的就永远无法触发了,因为有item已经满足条件返回了。可以理解为代码中的if语句。 ---------------------------------------------------- 关于listview和button都要改变android原来控件的背景,在网上查找了一些资料不是很全,所以现在总结一下android的selector的用法。 首先android的selector是在drawable/xxx.xml中配置的。 先看一下listview中的状态: 把下面的XML文件保存成你自己命名的.xml文件(比如list_item_bg.xml),在系统使用时根据ListView中的列表项的状态来使用相应的背景图片。 drawable/list_item_bg.xml

好程序员 2015最新Android应用开发基础教程

好程序员2015Android最新开发应用基础教程 适用人群:适用于零基础入学者 课程简介:本套课程结合最新Android新特性,结合最新技术特点所录制,此次课程我们主要讲解,Android基本UI及事件机制,Android四大组件的应用,Android中多线程的使用和Handler原理,Android中Fragment和ViewPager的使等,Android开发中常用知识点和功能讲解。 你会学到哪些? 掌握Android基本UI及事件机制 掌握Android四大组件的应用 掌握Android中多线程的使用和Handler原理 掌握Android中Fragment和ViewPager的使用 掌握菜单、通知、对话框的使用 掌握ListView、BaseAdapter的使用 掌握项目中通用的UI控件(滚动控件、网页控件、视频控件等) 掌握自定义控件和事件分发机制掌握实际项目开发流程和必备常识 1.Activity组件与Intent意图 1.1_activity_01 1.2_activity_02 1.3_activity_03 1.4_activity_04_task 1.5_activity_05

1.6_intent 2.网络操作与数据解析 1.7_AsyncTask01 3.UI(二) 1.8_Spinner_SimpleAdatper1 1.9_AutoCompleteTextView_ListView01 2.0_ListView02 2.1_BaseAdapter01 2.2_ListView04_News 2.3_ListView04_OnScrollListener 2.4_ListView05_ConvertView 2.5_ListView06_Person 2.6_ListView07_Item分类 2.7_ListView08_重构BaseAdapter 2.8_GridView 4.菜单、对话框、通知和Toast 2.9_Menu 3.0_Dialog01 3.1_Dialog02-03

Tongweb安装配置手册簿

1.1L inux平台下Tongweb服务器安装 在进行安装前请确认是否已经安装1.5版本的jdk,以下安装以Tongweb 4.8为例,目前管信部4A用的也是Tongweb 4.8(不支持1.6版本的jdk)版本。JDK的安装见(6.2.1)找到Tongweb4.8安装介质所在的文件夹,如下图所示 图 1.5.1-1 安装介质路径 直接运行安装程序,如下图; 图 1.5.1-2 执行安装命令 图 1.5.1-3 正在安装 随后会显示图形安装界面,如下图所示

此时Tongweb 4.8安装成功。 注意:若执行操作后提示错误信息为: 代表权限不够,执行如下命令:chmod +x *.bin 1.2注册Tongweb服务器 复制license.dat 到安装目录,如下图所示 注:图例将Tongweb安装于root目录下,同时也可以直接将License传到安装目录。 1.3L inux平台下测试Tongweb 1.3.1.1.1.1启动Tongweb 4.8 通过终端或者第三方客户端登录到启动命令所在目录:如下图

图 1.5.1-1-1 命令目录 后台启动命令(推荐使用) sh startnohup.sh 前台启动命令(该终端或者第三方客户端关闭的话,Tongweb服务也将关闭) ./tongserver.sh 或者是 ./tongserver.sh start 如果启动服务成功则应该出现下图所示的【system ready】 图 1.5.1-2 启动成功 1.3.1.1.1.2停止Tongweb 4.8 和启动Tongweb 命令目录一样, 停止服务命令:./tongserver.sh stop 1.4访问Tongweb 安装、启动成功后访问http://127.0.0.1:8001/console会出现Tongweb的控制台,如下图所示

android中sharp的使用

android:shape的使用 Android中常常使用shape来定义控件的一些显示属性,今天看了一些shape的使用,对shape有了大体的了解,稍作总结: 先看下面的代码:

solid:实心,就是填充的意思 android:color指定填充的颜色 gradient:渐变 android:startColor和android:endColor分别为起始和结束颜色, ndroid:angle是渐变角度,必须为45的整数倍。 另外渐变默认的模式为android:type="linear",即线性渐变,可以指定渐变为径向渐变,android:type="radial",径向渐变需要指定半径 android:gradientRadius="50" 。 stroke:描边 android:width="2dp" 描边的宽度,android:color 描边的颜色。 我们还可以把描边弄成虚线的形式,设置方式为: 其中android:dashWidth表示'-'这样一个横线的宽度,android:dashGap表示之间隔开的距离。 corners:圆角 android:radius为角的弧度,值越大角越圆。 我们还可以把四个角设定成不同的角度,方法为:

这里有个地方需要注意,bottomLeftRadius是右下角,而不是左下角,记得别搞错了。 还有网上看到有人说设置成0dp无效,不过我在测试中发现是可以的,我用的是2.2,可能修复了这个问题吧,如果无效的话那就只能设成1dp了。 padding:间隔 这个就不用多说了,XML布局文件中经常用到。 大体的就是这样,以下是一个使用的具体示例:用在Selector中作为Button 的背景,分别定义了按钮的一般状态、获得焦点状态和按下时的状态,具体代码如下: main.xml: button_selector.xml:

web服务器系统安装步骤

3#服务器安装步骤: 准备:1.系统盘;2.IBM Xseries235 驱动程序;3.OfficeXP;4.iFIX3.0及iWEBServer;5.10Users Update软盘。 开始:1.安装Windows2000 Server; 注:IBMServer安装Windows2000时需IBM引导盘进行引导安装,否则无法进行安装,安装过程中时区、语言的选择尤为重要,如果选择错误将有可能引起系统异常;引导盘安装程序是将2000安装盘上的文件复制到硬盘上进行安装的,所以中途不可再从光盘引导启动。 2.驱动程序安装; 注:当系统安装完成后,基本所有驱动程序都将被自动安装完成,这时打开设备管理器将会看到一个“未知设备”,双击“未知设备”安装驱动程序:IBM_Drivers目录中的“actpci”文件夹中。 3.系统配置(日期、时间格式); 4.系统正常运行后,利用Ghost备份系统; 5.安装OfficeXP; 6.iFIX安装; 7.配置iFIX SCU 以及host文件,配置如下: 127.0.0.1 localhost 172.16.14.11 SCADA SCADA1 172.16.14.12 SCADA SCADA2 172.16.14.13 SCADA3

172.16.14.14 FIX FIX1 172.16.14.15 FIX FIX2 172.16.14.16 FIX FIX3 172.16.14.17 FIX FIX4 172.16.14.18 FIX FIX5 注:SCU配置,报警配置:Alarm Summary Service启用、Alarm History Service启用、报警网络服务启用、报警启动队列服务启用;网络配置:按host文件中顺序添加远程节点,必须严格按照顺序;安全配置:WEB服务器可不启用安全。 配置iFIX的启动画面,“工作台”菜单下的“用户首选项”中配置工作台以运行方式启动,启动画面为:“DataTransfer.grf、rundata_oracle.grf、power_mes.grf、K9aircondition.grf”。 8.WebServer安装; 9.WebServer 10 User Update; 10.复制web页至C:\Inetpub\wwwroot\FIXPics\ 目录下,并配 置IIS服务; 注:当通过IE浏览器打开Web画面时可能会弹出:“This error’s key was AAGCGI_MaxName,and its location was parse_list”的错误,此时可通过以下方法解决:找到“C:\WINNT\AAGWEB.ini”文件,双击打开,找到“MaxName=100 MaxSamples=100”将这两项改为“MaxName=3000 MaxSamples=3000”即可。还有可能会出现aagwebdb 为只读的错误,解决方法见柳州卷烟厂动力能源管理中心

SQL语句 SELECT LIKE like用法详解

SQL语句 SELECT LIKE like用法详解 2009-12-16 13:44 LIKE语句的语法格式是:select * from 表名 where 字段名 like 对应值(子串),它主要是针对字符型字段的,它的作用是在一个字符型字段列中检索包含对应子串的。 假设有一个数据库中有个表table1,在table1中有两个字段,分别是name 和sex二者全是字符型数据。现在我们要在姓名字段中查询以“张”字开头的记录,语句如下: select * from table1 where name like "张*" 如果要查询以“张”结尾的记录,则语句如下: select * from table1 where name like "*张" 这里用到了通配符“*”,可以说,like语句是和通配符分不开的。下面我们就详细介绍一下通配符。 多个字符 * c*c代表cc,cBc,cbc,cabdfec等 它同于DOS命令中的通配符,代表多个字符。 多个字符 % %c%代表agdcagd等 这种方法在很多程序中要用到,主要是查询包含子串的。 特殊字符 a a代表a*a 代替* 单字符 ? b?b代表brb,bFb等 同于DOS命令中的?通配符,代表单个字符 单数字 # k#k代表k1k,k8k,k0k 大致同上,不同的是代只能代表单个数字。 字符范围 - [a-z]代表a到z的26个字母中任意一个 指定一个范围中任意一个 续上

排除 [!字符] [!a-z]代表9,0,%,*等 它只代表单个字符 数字排除 [!数字] [!0-9]代表A,b,C,d等 同上 组合类型 字符[范围类型]字符 cc[!a-d]#代表ccF#等 可以和其它几种方式组合使用 例:假设表table1中有以下记录: name sex 张小明男 李明天男 李a天女 王5五男 王清五男 下面我们来举例说明一下: 查询name字段中包含有“明”字的。 select * from table1 where name like '%明%' 查询name字段中以“李”字开头。 select * from table1 where name like '李*' 查询name字段中含有数字的。 select * from table1 where name like '%[0-9]%' 查询name字段中含有小写字母的。 select * from table1 where name like '%[a-z]%' 查询name字段中不含有数字的。 select * from table1 where name like '%[!0-9]%' 我们着重要说明的是通配符“*”与“%”的区别。 select * from table1 where name like '*明*' select * from table1 where name like '%明%' 大家会看到,前一条语句列出来的是所有的记录,而后一条记录列出来的是name字段中含有“明”的记录,所以说,当我们作字符型字段包含一个子串的查询时最好采用“%”而不用“*”,用“*”的时候只在开头或者只在结尾时,而不能两端全由“*”代替任意字符的情况下。 大家在写sql 语句的时候,如果是 select .. where 类型的语句,有注意到条件的前后顺序吗?我今天做个小实验。 比如查询地址里包含“海口市”及“振兴路” 两个关键字的数据,一般时候可能会用

Android开发编码规范_Android教程

Android开发编码规范 1、java代码中不出现中文,最多注释中可以出现中文 2、局部变量命名、静态成员变量命名 只能包含字母,单词首字母出第一个外,都为大写,其他字母都为小写 3、常量命名 只能包含字母和_,字母全部大写,单词之间用_隔开 4、layout中的id命名 命名模式为:view缩写_模块名称_view的逻辑名称 view的缩写详情如下 LayoutView:lv RelativeView:rv TextView:tv ImageView:iv ImageButton:im Button:btn 5、activity中的view变量命名 命名模式为:逻辑名称+view缩写 建议:如果layout文件很复杂,建议将layout分成多个模块,每个模块定义一个moduleViewHolder,其成员变量包含所属view 6、strings.xml中的id命名 命名模式:activity名称_功能模块名称_逻辑名称/activity名称_逻辑名称 /common_逻辑名称 strings.xml中,使用activity名称注释,将文件内容区分开来 drawable中的图片命名 命名模式:activity名称_逻辑名称/common_逻辑名称 7、styles.xml:将layout中不断重现的style提炼出通用的style通用组件,放到styles.xml中; 8、使用layer-list和selector 9、图片尽量分拆成多个可重用的图片 10、服务端可以实现的,就不要放在客户端 11、引用第三方库要慎重,避免应用大容量的第三方库,导致客户端包非常大 12、处理应用全局异常和错误,将错误以邮件的形式发送给服务端

[MSSQL] - SELECT语句使用大全

SELECT语句使用大全 虽然 SELECT 语句的完整语法比较复杂,但是大多数 SELECT 语句都描述结果集的四个主要属性 1、结果集中的列的数量和属性。 2、从中检索结果集数据的表,以及这些表之间的所有逻辑关系。 3、为了符合 SELECT 语句的要求,源表中的行所必须达到的条件。不符合条件的行会被忽略。 4、结果集的行的排列顺序。 它的主要子句可归纳如下: SELECT select_list --描述结果集的列 INTO new_table_name --指定使用结果集来创建新表 FROM table_list --包含从中检索到结果集数据的表的列表[返回结果集的对象]。 [ WHERE search_conditions ] --WHERE 子句是一个筛选,它定义了源表中的行要满足 SELECT 语句的要求所必须达到的条件 [ GROUP BY group_by_list ] --根据 group_by_list 列中的值将结果集分成组[ HAVING search_conditions ] --结果集的附加筛选 [ ORDER BY order_list [ ASC | DESC ] ] --结果集的附加筛选 一、使用选择列表 1、使用 *号来选择所有列;使用“[表名|别名]。[字段]”选取特定的列。 2、AS 子句可用来更改结果集列的名称或为派生列分配名称,也可以使用空格代替 如: SELECT Name AS Name1,Name Name2 FROM Product ORDER BY Name ASC 3、使用 DISTINCT 消除重复项 如:select distinct [Year] from A 4、使用 TOP 和 PERCENT 限制结果集数量 TOP ( expression ) [ PERCENT ] [ WITH TIES ] --expression 数量、PERCENT按百分比返回数据、WITH TIES返回排序与最后一行并列的行。 如:获取成绩前三名的同学 select top 3 * from Score order by Num desc --不考虑成绩并列 select top 3 WITH TIES * from Score order by Num desc --可解决成绩并列的问题 5、选择列表中的计算值 选择的列不但可以包括数据表列,还可以包括计算值,这些结果集列被称为派生列。 计算并且包括以下运算: 对数值列或常量使用算术运算符或函数进行的计算和运算。如SUM(),

安卓开发实验报告

安卓开发实验报告 目录 一、页面跳转 二、长按图标抖动以及显示删除 一、页面跳转 功能:通过点击button实现2个activity之间的跳转。 1.设置监听器监听点击button 2.使用intent传输数据

完整代码 1.ui_test.java publicclass UI_Test extends Activity { @Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(https://www.360docs.net/doc/c43928717.html,yout.incident_activity_1); Button bt = (Button)findViewById(R.id.login); bt.setOnClickListener(new OnClickListener()); } class OnClickListener implements View.OnClickListener{ publicvoid onClick(View v){ EditText name = (EditText)findViewById(https://www.360docs.net/doc/c43928717.html,); EditText password = (EditText)findViewById(R.id.password); Bundle data=new Bundle(); data.putString("name", name.getText().toString()); data.putString("password", password.getText().toString()); Intent intent = new Intent(UI_Test.this,UI_Result.class); intent.putExtras(data); startActivity(intent); } } 2.ui_result.java publicclass UI_Result extends Activity { @Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(https://www.360docs.net/doc/c43928717.html,yout.incident_activity_2); TextView name = (TextView)findViewById(https://www.360docs.net/doc/c43928717.html,Show); TextView password = (TextView)findViewById(R.id.passwordShow); Intent intent=getIntent(); Bundle result = intent.getExtras(); name.setText("您的用户名为: "+result.getString("name")); password.setText("您的密码为: "+result.getString("password"));

第1节-基本的SQL-SELECT语句

基本的SQL-SELECT语句 1.查看表结构 sql>desc 表名称; 2.查询所有列 select * from 表名称; 3. 查询指定列 select 列名称1 ,列名称2 ,列名称3 from 表名称; 4.如何取消重复行 select distinct 列名称1 ,列名称2 from 表名称; 5. 使用算数表达式 ?显示每个雇员的年工资 select sal*13+nvl(comm,0)*13 "年工资",ename,comm from emp; 6. 使用列的别名 select ename "姓名",sal*12 as "年收入" from emp; 7.如何处理null值(空值不是空格或者0) 使用nvl函数来处理 8. 如何连接字符串(||) selectename || 'is a ' || job from emp; SQL语句分为以下三种类型: ●DML: Data Manipulation Language 数据操纵语言 ●DDL: Data Definition Language 数据定义语言 ●DCL: Data Control Language 数据控制语言

DML用于查询与修改数据记录,包括如下SQL语句: ●INSERT:添加数据到数据库中 ●UPDATE:修改数据库中的数据 ●DELETE:删除数据库中的数据 ●SELECT:选择(查询)数据 SELECT是SQL语言的基础,最为重要。 DDL用于定义数据库的结构,比如创建、修改或删除数据库对象,包括如下SQL语句: ●CREATE TABLE:创建数据库表 ●ALTER TABLE:更改表结构、添加、删除、修改列长度 ●DROP TABLE:删除表 ●CREATE INDEX:在表上建立索引 ●DROP INDEX:删除索引 DCL用来控制数据库的访问,包括如下SQL语句: ●GRANT:授予访问权限 ●REVOKE:撤销访问权限 ●COMMIT:提交事务处理 ●ROLLBACK:事务处理回退 ●SAVEPOINT:设置保存点 ●LOCK:对数据库的特定部分进行锁定

2-apache Apache_Web 服务器安装部署手册档

重要提示 Web服务器包括apache的安装部署和W AS7 Plugin安装部署两部分,如果的websphere应用服务器使用非集群模式,plugin则不需要安装,只需配置本文2.1章节内容,如果websphere 应用服务器使用群集模式,则需要按照本文2.2章节进行plugin安装配置。 1 Apache安装 Apache的安装和配置现在可以采用脚本自动化安装,脚本就是139ftp上的 apache_install_script.sh 请下载到web服务器中,并执行即可。 注意:在执行脚本安装前请确认web服务器的/opt/apache下没有安装过apache,并且web 服务器能上外网(能ping通https://www.360docs.net/doc/c43928717.html,) 成功安装apache并测试通过后即可直接继续本文第二章节Was7 Plugin安装 在root下进行root进入方法#su 然后输入密码 1.1 准备安装 关闭系统自带的web服务: #chkconfig httpd off 在线安装gcc #yum install gcc cc 下载并解压安装程序: #cd ~/ #wget https://www.360docs.net/doc/c43928717.html,/httpd/httpd-2.2.15.tar.gz #tar –zxvf httpd-2.2.15.tar.gz -C /usr/src Web 服务器安装部署手册 Page 4 of 21 1.2 安装Apache Web Server 进入源码目录: #cd /usr/src/httpd-2.2.15 编译源文件: #./configure //(安装到默认目录) 形成安装文件: #make 安装程序: #make install 1.3 验证安装 进入安装后目录: # cd /opt/apache/apache-2.2.15/bin 检查进程模式: #./apachectl –l Compiled in modules: core.c worker.c http_core.c mod_so.c 启动Apache Web Server:

SELECT语句练习题答案

SELECT 语句练习题 有下列四个表: 1、学生表 S_NO S_NAME S_SEX S_BIRTHDAY CLASS 108曾华男1905-5-2295033 105匡明男1905-5-1895031 107王丽女1905-5-795033 101李军男1905-5-995033 109王芳女1905-5-1895031 103陆君男1905-5-2095031 2、教师表 T_NO T_NAME TSEX T_BIRTHDAY PROF DEPART 804李诚男1958-12-2副教授计算机系856张旭男1969-3-12讲师电子工程系825王萍女1972-5-5助教计算机系831刘冰女1977-8-14助教电子工程系 3、课程表 C_NO C_NAME T_NO 3-105计算机导论825 3-245操作系统804 6-166数据电路856 9-888高等数学100 4、成绩表 S_NO C_NO DEGREE 1033-24586 1053-24575 1093-24568 1033-10592 1053-10588 1093-10576 1013-10564 1073-10591 1083-10578 1016-16685 1076-10679 1086-16681 Select 语句的最基本结构:Select …. From ….where order by:排序子句(ASC:升序,DESC:降序)

like:模式匹配(通配符:% 可以匹配任意类型和长度的字符; _ 任意单个字符。 聚合函数(SUM A VG、COUNT、COUNT(*)、MAX、MIN) GROUP BY:分组 1、查询Student表中的所有记录的S_NAME、S_SEX和Class列。 2、查询教师所有的单位即不重复的Depart列。 3、查询Student表的所有记录。 4、查询Score表中成绩在60到80之间的所有记录。 5、查询Score表中成绩为85,86或88的记录。 6、查询Student表中“95031”班或性别为“女”的同学记录。 7、以Class降序查询Student表的所有记录。 8、以C_NO升序、Degree降序查询Score表的所有记录。 9、查询“95031”班的学生人数。 10、查询Score表中的最高分的学生学号和课程号。 11、查询‘3-105’号课程的平均分。 12、查询Score表中至少有5名学生选修的并以3开头的课程的平均分数。 13、查询最低分大于70,最高分小于90的S_NO列。 14、查询所有学生的S_NAME、C_NO和Degree列。 15、查询所有学生的S_NO、C_NAME和Degree列。 16、查询所有学生的S_NAME、C_NAME和Degree列。 17、查询“95033”班所选课程的平均分。 SQL语句练习题参考答案 1、select S_NAME,S_SEX,Class from Student; 2、select distinct depart from teacher; 3、select S_NO as '学号',S_NAME as '姓名',S_SEX as '性别',S_BIRTHDAY as'出生日期',Class as'班号'from student; 或 select S_NO as 学号,S_NAME as 姓名,S_SEX as 性别,S_BIRTHDAY as 出生日期,Class as 班号from student; 4、select * from score where degree between 60 and 80; 或select * from score where degree>=60 and degree<=80; 5、select * from score where degree in (85,86,88); 6、select * from student where class='95031'or S_SEX='女'; 7、select * from student order by class desc; 8、select * from score order by C_NO asc ,degree desc; 或select * from score order by C_NO ,degree desc; 9、select count(*) as CNT from student where class='95031'; 10、select S_NO as '学号',C_NO as '课程号', degree as '最高分' from score where degree=(select max(degree) from score) 11、select avg(degree)as 课程平均分from score where C_NO='3-105'; 12、select C_NO,avg(degree) from score where C_NO like'3%'group by C_NO having count(*) >5; 13、select S_NO from score group by S_NO having min(degree)>70 and max(degree)<90; 14、select student.S_NAME,score.C_NO,score.degree from student,score where student.S_NO=score.S_NO; 15、select x.S_NO,y.C_NAME,x.degree from score x,course y where x.C_NO=y.C_NO; 16、select x.S_NAME,y.C_NAME,z.degree from student x,course y,score z where x.S_NO=z.S_NO and z.C_NO=y.C_NO;

常用SELECT语句汇总

常用SELECT语句汇总 一、单表查询 (一)按照条件查询相关记录 Select 字段1,字段2……字段N from 表 where 条件含义:从表中根据where 条件查询记录,每条记录显示的字段按照字段1、字段2….字段N的设置显示 注:select语句中的标点符号及运算符必须使用英文半角字符。 例1:从凭证库中查询2004年1月31日的凭证,每条凭证只显示凭证日期、凭证号、科目名称、借方金额、贷方金额、会计月份 6个字段 Select 凭证日期,凭证号,科目名称,借方金额,贷方金额,会计月份 From 凭证库 where 凭证日期=’2004-1-31’ 例2:根据业务_个人基本情况表,找出缴存状态为”正常”的记录,查出的记录只显示姓名、身份证号、单位账号及个人账号 4个字段 Select 个人姓名,身份证号,单位账号,个人账号 from 业务_个人基本情况表 where 账户状态=’1’ 例3:从科目余额表中查询出2010年借方金额大于50万或2010年借方金额小于10万的记录,每条记录只显示摘要、科目编码、借方金额、贷方金额、年度5个字段 Select摘要,科目编码,借方金额,贷方金额,年度 From 科目余额 where(借方金额>500000 and 年度=2010) or (借方金额<100000 and 年度=2010) Select top 100 字段1,字段2……字段N from 表 where 条件含义:从表中根据where 条件查询记录,显示前100条记录,每条记录按照字段1、字段2….字段N的设置显示 例1:从凭证库中查询2004年1月31日的前100条凭证,每条 2 凭证只显示凭证日期、凭证号、科目名称、借方金额、贷方金额、会计月份 6个字段Select top 100凭证日期,凭证号,科目名称,借方金额,贷方金额,会计月份 From 凭证库where 凭证日期=’2004-1-31’ 例2:根据业务_个人基本情况表,找出缴存状态为”正常”的前100条记录 Select top 100个人姓名,身份证号,单位账号,个人账号 from 业务_个人基本情况表where 账户状态=’1’ (二)通配符的使用 *表示将全部的字段内容都显示出来 例1:从业务_电子警察表中筛选出无车号或者车牌号小于3位的记录 Select * from 业务_电子警察 where 车号=’’ or Len(车号)<3 例2:从科目余额表中查询出2002年收入大于50万的记录 Select * from 科目余额 where 借方金额>500000 and 年度=2002 %表示零或多个字符 例1:从凭证库中查询2003年各月的房租收入情况 Select month(凭证日期) as 月份, sum(贷方金额) as 房租金额 from 凭证 where 摘要 like ‘%房租%’ and 年度=2003 例2:从凭证库中查询 2008年包含税的记录 Select * from 凭证库 where摘要 like ‘%税%’ and 年度=2008 _表示任何一个字符 例1:根据科目余额表查询出目编码为10开头的一级科目记录 Select * from 科目余额

相关文档
最新文档