网络编程03

1.用于排错的TCP状态转换图

TCP状态转换图:
1 三次握手过程:
客户端: SYN_SENT—connect()
服务端: LISTEN–listen() SYN_RCVD
当三次握手完成后, 都处于ESTABLISHED状态
2 数据传输过程中状态不发生变化, 都是ESTABLISHED状态
3 四次挥手过程:
主动关闭方: FIN_WAIT_T FIN_WAIT_2 TIME_WAIT
被动关闭方: CLOSE_WAIT LAST_ACK
在这里插入图片描述

  • 思考题?
    1 SYN_SENT状态出现在哪一方? 客户端
    2 SYN_RCVD状态出现在哪一方? 服务端
    3 TIME_WAIT状态出现在哪一方? 主动关闭方
    4 在数据传输的时候没有状态变化.

  • TIME_WAIT是如何出现的:
    启动服务端, 启动客户端, 连接建好, 而且也可以正常发送数据;
    然后先关闭服务端, 服务端就会出现TIME_WAIT状态.

2.- 为什么需要2MSL时间:

原因之一: 让四次挥手的过程更可靠, 确保最后一个发送给对方的ACK到达;
若对方没有收到ACK应答, 对方会再次发送FIN请求关闭, 此时在2MS时间内被动关闭方仍然可以发送ACK给对方.

原因之二: 为了保证在2MS时间内, 不能启动相同的SOCKET-PAIR.
TIME_WAIT一定是出现在主动关闭的一方, 也就是说2MS是针对主动关 闭一方来说的;由于TCP有可能存在丢包重传, 丢包重传若发给了已经断 开连接之后相同的socket-pair(该连接是新建的, 与原来的socket-pair完 全相同, 双方使用的是相同的IP和端口), 这样会对之后的连接造成困扰, 严重可能引起程序异常.
在这段时间再启动会出现问题,出现错误:在这里插入图片描述

如何解决这个问题,设置端口复用技术----》》

3.设置端口复用

设置端口复用:
	int opt = 1;
	setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));

4.半关闭

  • 半关闭的概念:
    如果一方close, 另一方没有close, 则认为是半关闭状态, 处于半关闭状态的 时候, 可以接收数据, 但是不能发送数据. 相当于把文件描述符的写缓冲区 操作关闭了.
    注意: 半关闭一定是出现在主动关闭的一方.

  • shutdown和close的区别:

  • shutdown能够把文件描述符上的读或者写操作关闭, 而close关闭文件描述 符只是将连接的引用计数的值减1, 当减到0就真正关闭文件描述符了(父进程子进程).
    如: 调用dup函数或者dup2函数可以复制一个文件描述符, close其中一个并 不影响另一个文件描述符, 而shutdown就不同了, 一旦shutdown了其中一 个文件描述符, 对所有的文件描述符都有影响 .

  • 长连接和端连接的概念:
    连接建立之后一直不关闭为长连接;
    连接收发数据完毕之后就关闭为短连接;

5.心跳包

在这里插入图片描述
如何让心跳数据和正常的业务数据不混淆?
解决办法:
双方协商规则,如:在数据前面加一个报头,例如粘包的时候。

6.高并发服务器模型—select及相关函数的使用

(一个进程支持多个连接的情况,同时监听多个文件描述符,不使用多进程和多线程技术)select委托内核监控可读,可写,异常事件。

多路IO技术: select, 同时监听多个文件描述符, 将监控的操作交给内核去处理, 

数据类型fd_set: 文件描述符集合--本质是位图(关于集合可联想一个信号集sigset_t)
int select(int nfds, fd_set * readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
函数介绍: 委托内核监控该文件描述符对应的读,写或者错误事件的发生.
参数说明: 
	nfds: 最大的文件描述符+1
	readfds: 读集合, 是一个传入传出参数,程序中可以得到的参数,后续可使用
		传入: 指的是告诉内核哪些文件描述符需要监控
		传出: 指的是内核告诉应用程序哪些文件描述符发生了变化
	writefds: 写文件描述符集合(传入传出参数)
	execptfds: 异常文件描述符集合(传入传出参数)
	timeout: 
		NULL--表示永久阻塞, 直到有事件发生
		0 --表示不阻塞, 立刻返回, 不管是否有监控的事件发生
		>0--到指定事件或者有事件发生了就返回
	
返回值: 成功返回发生变化的文件描述符的个数
		失败返回-1, 并设置errno值.

另外,提供了一些供我们查询的函数:

void FD_CLR(int fd,fd_set *set);  //说明:从set集合中清除fd
int FD_ISSET(int fd,fd_set * set); //说明:在调用select()函数后,用FD_ISSET来检测fd是否在set集合中,当检测到fd在set中则返回真,否则,返回假(0) 
void FD_SET(int fd,fd_set *set);//说明:将fd添加到set集合中
void FD_ZERO(fd_et *set); //清楚文件描述符

7.使用select开发网络服务器的开发流程

使用select的开发服务端流程:
1 创建socket, 得到监听文件描述符lfd---socket()
2 设置端口复用-----setsockopt()
3 将lfd和IP  PORT绑定----bind()
4 设置监听---listen()
5 fd_set readfds;  //定义文件描述符集变量
  FD_ZERO(&readfds);  //清空文件描述符集变量  定义变量后进行初始化操作
  FD_SET(lfd, &readfds);//将lfd加入到readfds集合中;
  fd_set tmpfds;
  maxfd = lfd;
  while(1)
  {
  	tmpfds = readfds; //内核的值会改,因此定义一个临时变量进行存储,每次赋值????????
  	nready = select(maxfd+1, &tmpfds, NULL, NULL, NULL);
  	if(nready<0)  //数据异常
  	{
  		if(errno==EINTR)//被信号中断,不应该被认为异常
  		{
  			continue;  
  		}
  		break;
  	}
  	//可读事件发生
  	//有客户端连接请求到来,没告诉具体哪个:是写请求还是异常
  	if(FD_ISSET(lfd, &tmpfds))
  	{
  		//接受新的客户端连接请求,监听到的然后创建通信文件描述符
  		cfd = accept(lfd, NULL, NULL);
  		
  		//将cfd加入到readfds集合中,继续让内核进行监控
  		FD_SET(cfd, &readfds);
  		
  		//修改内核监控的文件描述符的范围,监控的数量随着也变化
  		if(maxfd<cfd)
  		{
  			maxfd = cfd;
  		}
  		
  		if(--nready==0)
  		{
  			continue;
  		}
  	}
  	
  	//并列的关系---加入,监听和发送数据
  	//有客户端数据发来,可能有多个,因此写在一个循环里,监听文件描述符
  	for(i=lfd+1; i<=maxfd; i++)
  	{
  		if(FD_ISSET(i, &tmpfds))
  		{
			//read数据,有数据,会返回,不会阻塞
  			n = read(i, buf, sizeof(buf));
  			if(n<=0)//对方关闭连接,那就关闭
  			{
  				close(i);
  				//将文件描述符i从内核中去除
  				FD_CLR(i, &readfds);
  			}
  			
  			//write应答数据给客户端
  			write(i, buf, n);
  		}
  		//如果监听不到,就退出,原来加了1,所以这块要减1
		if(--nready==0)
  		{
  			break;
  		}
  	}
  	
  	close(lfd);
  	
  	return 0;
  }
 
代码优化方向:
int client[1024]
for()
{
	client[i] = -1;
}

1 将通信文件描述符保存到一个整形数组中, 使用一个变量记录
  数组中最大元素的下标maxi.
2 如果数组中有无效的文件描述符, 直接跳过

代码实现:
在这里插入图片描述
代码优化方向:

1 将通信文件描述符保存到一个整形数组中, 使用一个变量记录
数组中最大元素的下标maxi.
2 如果数组中有无效的文件描述符, 直接跳过

8.使用select开发网络服务器的最终代码

//IO多路复用技术select函数的使用 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/select.h>

int main()
{
	int i;
	int n;
	int lfd;
	int cfd;
	int ret;
	int nready;
	int maxfd;//最大的文件描述符
	char buf[FD_SETSIZE];
	socklen_t len;
	int maxi;  //有效的文件描述符最大值
	int connfd[FD_SETSIZE]; //有效的文件描述符数组
	fd_set tmpfds, rdfds; //要监控的文件描述符集
	struct sockaddr_in svraddr, cliaddr;

	//创建socket
	lfd = socket(AF_INET, SOCK_STREAM, 0);
	if(lfd<0)
	{
		perror("socket error");
		return -1;
	}

	//允许端口复用
	int opt = 1;
	setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));

	//绑定bind
	svraddr.sin_family = AF_INET;
	svraddr.sin_addr.s_addr = htonl(INADDR_ANY);
	svraddr.sin_port = htons(8888);
	ret = bind(lfd, (struct sockaddr *)&svraddr, sizeof(struct sockaddr_in));
	if(ret<0)
	{
		perror("bind error");
		return -1;
	}

	//监听listen
	ret = listen(lfd, 5);
	if(ret<0)
	{
		perror("listen error");
		return -1;
	}

	//文件描述符集初始化
	FD_ZERO(&tmpfds);
	FD_ZERO(&rdfds);

	//将lfd加入到监控的读集合中
	FD_SET(lfd, &rdfds);

	//初始化有效的文件描述符集, 为-1表示可用, 该数组不保存lfd
	for(i=0; i<FD_SETSIZE; i++)
	{
		connfd[i] = -1;
	}

	maxfd = lfd;
	len = sizeof(struct sockaddr_in);

	//将监听文件描述符lfd加入到select监控中
	while(1)
	{
		//select为阻塞函数,若没有变化的文件描述符,就一直阻塞,若有事件发生则解除阻塞,函数返回
		//select的第二个参数tmpfds为输入输出参数,调用select完毕后这个集合中保留的是发生变化的文件描述符
		tmpfds = rdfds;
		nready = select(maxfd+1, &tmpfds, NULL, NULL, NULL);
		if(nready>0)
		{
			//发生变化的文件描述符有两类, 一类是监听的, 一类是用于数据通信的
			//监听文件描述符有变化, 有新的连接到来, 则accept新的连接
			if(FD_ISSET(lfd, &tmpfds))	
			{
				cfd = accept(lfd, (struct sockaddr *)&cliaddr, &len);			
				if(cfd<0)
				{
					if(errno==ECONNABORTED || errno==EINTR)
					{
						continue;
					}
					break;
				}

				//先找位置, 然后将新的连接的文件描述符保存到connfd数组中
				for(i=0; i<FD_SETSIZE; i++)
				{
					if(connfd[i]==-1)
					{
						connfd[i] = cfd;
						break;
					}
				}
				//若连接总数达到了最大值,则关闭该连接
				if(i==FD_SETSIZE)
				{	
					close(cfd);
					printf("too many clients, i==[%d]\n", i);
					//exit(1);
					continue;
				}

				//确保connfd中maxi保存的是最后一个文件描述符的下标
				if(i>maxi)
				{
					maxi = i;
				}

				//打印客户端的IP和PORT
				char sIP[16];
				memset(sIP, 0x00, sizeof(sIP));
				printf("receive from client--->IP[%s],PORT:[%d]\n", inet_ntop(AF_INET, &cliaddr.sin_addr.s_addr, sIP, sizeof(sIP)), htons(cliaddr.sin_port));

				//将新的文件 描述符加入到select监控的文件描述符集合中
				FD_SET(cfd, &rdfds);
				if(maxfd<cfd)
				{
					maxfd = cfd;
				}

				//若没有变化的文件描述符,则无需执行后续代码
				if(--nready<=0)
				{
					continue;
				}	
			}

			//下面是通信的文件描述符有变化的情况
			//只需循环connfd数组中有效的文件描述符即可, 这样可以减少循环的次数
			for(i=0; i<=maxi; i++)
			{
				int sockfd = connfd[i];
				//数组内的文件描述符如果被释放有可能变成-1
				if(sockfd==-1)
				{
					continue;
				}

				if(FD_ISSET(sockfd, &tmpfds))
				{
					memset(buf, 0x00, sizeof(buf));
					n = read(sockfd, buf, sizeof(buf));
					if(n<0)
					{
						perror("read over");
						close(sockfd);
						FD_CLR(sockfd, &rdfds);
						connfd[i] = -1; //将connfd[i]置为-1,表示该位置可用
					}
					else if(n==0)
					{
						printf("client is closed\n");	
						close(sockfd);
						FD_CLR(sockfd, &rdfds);
						connfd[i] = -1; //将connfd[i]置为-1,表示该位置可用
					}
					else
					{
						printf("[%d]:[%s]\n", n, buf);
						write(sockfd, buf, n);
					}

					if(--nready<=0)
					{
						break;  //注意这里是break,而不是continue, 应该是从最外层的while继续循环
					}
				}	
			}
		}	
	}

	//关闭监听文件描述符
	close(lfd);

	return 0;
}

9.select的优缺点

select优点:
1 一个进程可以支持多个客户端
2 select支持跨平台
select缺点:
1 代码编写困难
2 会涉及到用户区到内核区的来回拷贝
3 当客户端多个连接, 但少数活跃的情况, select效率较低
例如: 作为极端的一种情况, 3-1023文件描述符全部打开, 但是只有1023有发送数据, select就显得效率低下
4 最大支持1024个客户端连接
select最大支持1024个客户端连接不是有文件描述符表最多可以支持1024个文件描述符限制的, 而是由FD_SETSIZE=1024限制的.

FD_SETSIZE=1024 fd_set使用了该宏, 当然可以修改内核, 然后再重新编译内核, 一般不建议这么做.

作业:
编写代码, 让select监控标准输入, 监控网络, 如果标准输入有数据就写入网络, 如果网络有数据就读出网络数据, 然后打印到标准输出.
注意: select不仅可以监控socket文件描述符, 也可以监视标准输入

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
◆ 01.htm 1、怎么用mscomm控件检测modem是否与计算机联接正确?2、如何用mscomm挂断modem与别的电话机间的连接?(已接通) ◆ 02.htm CWinInetConnection---一个封装了WinInet API函数的类 ◆ 03.htm MODEM通讯意外处理 ◆ 04.htm MsComm 文字传输 ◆ 05.htm PING一个IP地址(向它发送一个数据包并等待回应) ◆ 06.htm SMTP协议简介 (Simple Mail Transfer Protocol) ◆ 07.htm VB5.0 中远程数据库的访问 ◆ 08.htm VB下如何编写CRC校验程序 ◆ 09.htm VB中Winsock控制的UDP协议的使用 ◆ 10.htm Visual Basic 6中发送邮件的新方法 ◆ 11.htm Visual Basic通信程序设计 ◆ 12.htm Whois 示例程序 ◆ 13.htm Winsock Terminal示例程序 ◆ 14.htm WinSock断开导致客户端问题 ◆ 15.htm 把Outlook信箱中的附件另存为 ◆ 16.htm 保证连网计算机时间同步 ◆ 17.htm 编写网络寻呼机 ◆ 18.htm 编制自已的电话录音小程序 ◆ 19.htm 程序中如何启动默认的拨号连接 ◆ 20.htm 程序中如何启动默认的拨号连接? ◆ 21.htm 打开器并进入指定网址 ◆ 22.htm 打开一个直接到自己主页的器 ◆ 23.htm 得到用户的IP地址 ◆ 24.htm 电话拨号 ◆ 25.htm 电子邮件的标准格式 (RFC 822) ◆ 26.htm 断开拨号网络的连接 ◆ 27.htm 断开与 Internet 的连接 ◆ 28.htm 发送电子邮件附件 ◆ 29.htm 发送电子邮件附件1 ◆ 30.htm 发送电子邮件附件2 ◆ 31.htm 发送电子邮件附件3 ◆ 32.htm 发送电子邮件附件4 ◆ 33.htm 获得用户网络登录名 ◆ 34.htm 基 于Win95 的VB5 串 口 通 信 程 序 ◆ 35.htm 基于Win95的VB5串口通信程序 ◆ 36.htm 几个设置IE的API ◆ 37.htm 检测运程数据传送的断线 ◆ 38.htm 简单的聊天程序 ◆ 39.htm 简单电子邮件发送程序 ◆ 40.htm 建立拨号联接 ◆ 41.htm 将所有窗口最小化 ◆ 42.htm 利用IE控件访问Internet ◆ 43.htm 利用IE控件设计简易器 ◆ 44.htm 利用Mscomm32控件判断MODEM是否打开,或者正在工作,并且判断拨号时是否遇忙音 ◆ 45.htm 利用TAPI进行电话拨号 ◆ 46.htm 利用VB访问Internet ◆ 47.htm 利用VB设计聊天室 ◆ 48.htm 利用Visual Basic实现无线通讯 ◆ 49.htm 利用Winsock控件实现局域网通信 ◆ 50.htm 强制一个本地或远程NT系统关闭 ◆ 51.htm 取得网卡序列号 ◆ 52.htm 如何从 Internet 上取回某一个网页的內容? ◆ 53.htm 如何检测是否已连接到Internet? ◆ 54.htm 如何利用Winsock控件编写自己的Internet程序 ◆ 55.htm 如何每天抓取 Internet 上某一个网页中的图片来更换桌面的壁纸? ◆ 56.htm 如何启动拨号网路中的连线? ◆ 57.htm 如何使用MSCOMM32.OCX发送大于80H的字符,可否给个示例程序 ◆ 58.htm 如何通过VB获取网卡地址 ◆ 59.htm 如何用VB打开默认器或默认发信程序? ◆ 60.htm 如何用Visual Basic编写小型的网络系统 ◆ 61.htm 如何在程序中启动 NT 的【拨号连接】对话框 ◆ 62.htm 如何在程序中启动 NT 的【拨号连接】对话框? ◆ 63.htm 如何在网页上使用 VB5 制作的 ActiveX 控件? ◆ 64.htm 如何中断【拨号网络连接】 ◆ 65.htm 设计Browser及FTP程序 ◆ 66.htm 设计Chat程序 ◆ 67.htm 设计E-mail程序 ◆ 68.htm 设置计算机名称 ◆ 69.htm 使用VB获得一页的HTML代码 ◆ 70.htm 使用VB收发电子邮件 ◆ 71.htm 使用标签控件调出器 ◆ 72.htm 使用超链接和发送Email ◆ 73.htm 使用器的文件复制对话框 ◆ 74.htm 输入/输出篇 ◆ 75.htm 通过WnetEnumResource函数获得网络资源 ◆ 76.htm 通往 Internet 的捷径 ◆ 77.htm 显示计算机的名称 ◆ 78.htm 用 MAPI 控件实现发送邮件 ◆ 79.htm 用 WinSock 控件下载文件 ◆ 80.htm 用 Winsock 实现聊天的程序 ◆ 81.htm 用Internet Transfer编写FTP程序 ◆ 82.htm 用Sockets发送电子邮件 ◆ 83.htm 用VB 创 建 自 己 的 通 信 程 序 ◆ 84.htm 用VB5.0开发通信软件的技巧 ◆ 85.htm 用VB5开发IE ◆ 86.htm 用VB编写网络寻呼 ◆ 87.htm 用VB编写小型的网络系统 ◆ 88.htm 用VB创建自己的通信程序 ◆ 89.htm 用VB构建Internet的应用[微软提供] ◆ 90.htm 用VB开发标准CGI程序 ◆ 91.htm 用VB实现客户——服务器(TCP IP)编程实例 ◆ 92.htm 用VB实现客户服务器(TCPIP)编程实例 ◆ 93.htm 用VB实现聊天讨论室和点对点会话 ◆ 94.htm 用VB写一个定时PING某IP的程序 ◆ 95.htm 用VB制作器 ◆ 96.htm 用Visual Basic 5.0设计E-mail程序(MAPI) ◆ 97.htm 用Visual Basic6.0编写客户服务器程序 ◆ 98.htm 用Visual Basic创建FTP组件 ◆ 99.htm 用Visual Basic开发数据库器 ◆ 100.htm 用Visual Basic轻松地设计Browser及Ftp程序 ◆ 101.htm 用Winsock控件发信Email ◆ 102.htm 用Winsock控件实现文件的下载 ◆ 103.htm 用Winsock实现点对点通信 ◆ 104.htm 邮件检查程序(二) ◆ 105.htm 邮件检查程序(一) ◆ 106.htm 在VB程序中怎样挂断拨号网络 ◆ 107.htm 在VB中操纵OLE服务器应用程序 ◆ 108.htm 在VB中利用UDP协议编写聊天程序 ◆ 109.htm 在VB中模拟实现邮件传输 ◆ 110.htm 在VB中如何得到网络中某一台电脑(电脑名)的网卡地质? (自己的) ◆ 111.htm 在VB中实现文件上传 ◆ 112.htm 在VB中实现文件上载 ◆ 113.htm 在VB中使用UDP协议 ◆ 114.htm 在VB中用Outlook发电子邮件 ◆ 115.htm 在WindowsNT网络中广播消息 ◆ 116.htm 在程序中打开 Internet 拨号连接窗口 ◆ 117.htm 在一个单位内部或通过广域协议(如X.25)互联的行业内部都有几十或上万台计算机互联,用Intranet虽然可以建立聊天室,但实现点对点实时对话却比较困难。本人用Winsock和VB自制了一套聊天室和对话系统,特拿来供同行们参考。 ◆ 118.htm 在应用中集成器 ◆ 119.htm 在桌面上建立一个 Internet 快捷键 ◆ 120.htm 怎样接收电子邮件(POP3协议简介) ◆ 121.htm 怎样用VB得知系统当前是否处于internet链结状态 ◆ 122.htm 制作自己的网络搜索软件 ◆ 123.htm 自动更新工作站的应用程序 ◆ 124.htm 自己的IE——用VB制作器 ◆ 125.htm HTTP协议(学习笔记) ◆ 126.htm HTTP协议四--关于Chunked编码 ◆ 127.htm IE器完全控制 ◆ 128.htm OICQ服务器系统通讯协议 ◆ 129.htm POP3协议的基本命令 ◆ 130.htm RAS API上的其他Function ◆ 131.htm VB + API 获取 IE 的 “代理服务器” 配制 ◆ 132.htm vb调用winInet API接口post数据到指定的url ◆ 133.htm vb开发通信软件 ◆ 134.htm vb设计数据库电子邮件程序(1) ◆ 135.htm vb设计数据库电子邮件程序(2) ◆ 136.htm vb设计数据库电子邮件程序(3) ◆ 137.htm vb设计数据库电子邮件程序(4) ◆ 138.htm vb设计数据库电子邮件程序(5) ◆ 139.htm vb设计数据库电子邮件程序(6) ◆ 140.htm VB实现应用程序在局域网上自动更新 ◆ 141.htm VB邮件检查程序 ◆ 142.htm vb中从域名得到IP及从IP得到域名 ◆ 143.htm VB中检测是否连网 ◆ 144.htm WebClass实现动态WEB编程之理论篇 ◆ 145.htm Winsocket网络编程谈 ◆ 146.htm Winsock编程框架 ◆ 147.htm Winsock错误代码一览表 ◆ 148.htm 程式自动呼叫拨号网络(RAS API) ◆ 149.htm 打开一个超连接 ◆ 150.htm 得到登入windows 的人的id ◆ 151.htm 访问Internet并调用Explorer ◆ 152.htm 非同步文件下载类 ◆ 153.htm 给Outlook的所有用户发送信件 ◆ 154.htm 获得网卡的MAC地址 ◆ 155.htm 基于WinSock的小型网络管理系统及其实现 ◆ 156.htm 检测是否连接到Internet ◆ 157.htm 检测网络是否连通 ◆ 158.htm 建立Web的超链接树形图 ◆ 159.htm 建立你自己的器-Properties ◆ 160.htm 建立你自己的器-查看源文件 ◆ 161.htm 建立你自己的器-打印 ◆ 162.htm 建立你自己的器-打印设置 ◆ 163.htm 建立你自己的器-发送到FontPage ◆ 164.htm 建立你自己的器-发送到Visual Interdev ◆ 165.htm 建立你自己的器-发送到软盘 ◆ 166.htm 建立你自己的器-复制 ◆ 167.htm 建立你自己的器-另存为 ◆ 168.htm 建立你自己的器-全选 ◆ 169.htm 建立你自己的器-页面设置 ◆ 170.htm 开发通信软件的技术与技巧 ◆ 171.htm 开发网络应用的5个技巧 ◆ 172.htm 利用RAS调用在VB6.0中实现拨号上网 ◆ 173.htm 利用VB提取HTML文件中的EMAIL地址 ◆ 174.htm 枚举出局域网上所有网络资源 ◆ 175.htm 面向Internet的开发工具 ◆ 176.htm 你也可以YAI--VB5中Winsock控件的使用 ◆ 177.htm 判断一个文件是否在IE的缓存中 ◆ 178.htm 启动拨号网络中的连接 ◆ 179.htm 浅谈HTTP协议(二)--返回值 ◆ 180.htm 浅谈HTTP协议(一)--结构 ◆ 181.htm 如何利用 WebBrowser 控件显示 .GIF 动画? ◆ 182.htm 如何映射(中断网络磁盘) ◆ 183.htm 设计E-mail的接收部分 ◆ 184.htm 设置器默认网址 ◆ 185.htm 实现端口对端口的聊天 ◆ 186.htm 使用ASP建立Http组件 ◆ 187.htm 使用VB编写纯ASP程序 ◆ 188.htm 使用vb获取网上邻居里的计算机名 ◆ 189.htm 使用VB建立Web Server ◆ 190.htm 使用Visual Basic开发通讯软件 ◆ 191.htm 使用资源工具包执行本地和远程重新启动 ◆ 192.htm 谈谈远程控制中关于搜索、控制计算机的功能 ◆ 193.htm 压缩 Html ◆ 194.htm 用ASP、VB和XML建立互联网应用程序(1) ◆ 195.htm 用ASP、VB和XML建立互联网应用程序(2) ◆ 196.htm 用ASP、VB和XML建立互联网应用程序(3) ◆ 197.htm 用ASP、VB和XML建立互联网应用程序(4) ◆ 198.htm 用COMMUNICATION控件进行数据采集(学习笔记) ◆ 199.htm 用OLE自动化Outlook ◆ 200.htm ActiveX控件用于DHTML开发 ◆ 201.htm 用VB编写ActiveX DLL实现ASP编程 ◆ 202.htm 用VB编写Windows CGI应用程序 ◆ 203.htm 用VB编写标准CGI程序(上) ◆ 204.htm 用VB编写标准CGI程序(下) ◆ 205.htm 用VB编写收发电子邮件程序 ◆ 206.htm 用VB编写网络监控软件 ◆ 207.htm 用VB编写异步多线程下载程序 ◆ 208.htm 用VB导入导出IE器收藏夹 ◆ 209.htm 用VB定制合路器 ◆ 210.htm 用VB和XML建立集中式应用程序 ◆ 211.htm 用VB将Html转换为文本文件 ◆ 212.htm 用VB开发分布式应用 ◆ 213.htm 用VB设计基于代理服务器的网络计费系统 ◆ 214.htm 用VB制作文件下载程序 ◆ 215.htm 用Visual Basic 实现无线通讯 ◆ 216.htm 用Winsock制作一套聊天室和对话系统 ◆ 217.htm 远程共享显示及声音的实现 ◆ 218.htm 远程启动机器ABC API解决方案 ◆ 219.htm 远程启动机器ABC WMI解决方案 ◆ 220.htm 在VB5中利用Winsock和msDNS控件进行 ◆ 221.htm 找出计算机上当前登录入网的用户 ◆ 222.htm 用VB5 Winsock控件创建TCP(IP)客户机 服务器程序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值