仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 753|回复: 8
打印 上一主题 下一主题

[学习教程] NET网页编程之Socket编程(二)

[复制链接]
海妖 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-16 14:22:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
它有很多缺点的,有兴趣可以到网上去搜索一下。于是微软有发明了“下一代”C++:C++/CLI语言,这个可以解决在.NETFramework中,托管C++产生的问题。在《程序员》杂志上,lippman和李建中合作连载介绍了C++/CLI语言。本章接上章Socket编程(一)

/*SIDCHLD旌旗灯号处置函数*/
vodsig_chld(intsigno)
{
pid_tpid;
intstat;
while((pid=waitpid(-1,&stat,WNOHANG))>0);
return;
}
[client]
sockfd=socket(AF_INET,SOCK_STREAM,0);
bzero(&servaddr,sizeof(servaddr));
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_familf=AF_INET;
servaddr.sin_port=htons(SERV_PORT);
inet_pton(AF_INET,SERV_IP_STRING,&servaddr.sin_addr);
connect(sockfd,(structsockaddr*)&serv_addr,sizeof(servaddr);
….//process
exit(0);


停止收集毗连的一般办法是挪用close(),可是有两个限定:
1.将形貌字的会见计数-1,到0时才引发TCP毗连的停止序列(抛弃吸收缓冲区里的数据,发送发送缓冲区里的数据,假如形貌字的会见计数为0,在数据以后收回FIN)

2.停止了数据传输的两个偏向,读和写shutdown能够封闭一半毗连,并且在发完发送缓冲区里的数据后当即收回FIN序列
UDP无毗连编程时,在SERVER端少了accept()和listen(),客户端少了connect(),由于是无毗连的,以是不必close(),读写一样平常用sendto()和recvfrom()。假如client发送的数据被路由抛弃大概服务器的应对信息丧失,那末client将一向堵塞,直到使用设置的超时抵达,UDP必要使用来做承受确认、传输超时大概重传的机制。

一样平常的,UDP服务属于迭代的,而TCP服务年夜多半是并发的。用I/O复用体例(select())完成(能够制止为每一个客户端毗连创立一个历程的开支):
[server]
intclient[FD_SETSIZE];
fd_setallset,rset;

maxfd=listenfd;
maxi=-1;
for(I=0;I<FD_SETSIZE;i++)
client=-1;
FD_ZERO(&allset);
FD_SET(listenfd,&allset);
For(;;){
rset=allset;
nready=select(maxfd+1,&rset,NULL,NULL,NULL);
if(FD_ISSET(listenfd,&rset)){//新毗连
clilen=sizeof(cliaddr);
connfd=accept(listenfd,(structsockaddr*)&cliaddr,&clilen);
for(i=0;I<FD_SETSIZE;i++){
if(client<0){//找出client数组中第一个-1的单位寄存已毗连的socket
client=connfd;
break;
}

if(IFD_SETSIZE)
fprintf(stderr,“toomanyclients
”);
FD_SET(connfd,&allset);
If(connfd>maxfd)
Maxfd=connfd;
If(I>maxi)
Maxi=I;
If(--nready<=0)
Continue;
}

for(I=0;I<=maxi;i++){
if((sockfd=client)<0)
continue;
if(FD_ISSET(sockfd,&rset)){
if((n=read(sockfd,…))0){//客户端已封闭毗连
close(sockfd);
FD_CLR(sockfd,&allset);
Client=-1;
}else
{
…//process
if(--nready<=0)
break;
}
}
}
}


用这类办法有一个成绩:
简单受DDOS打击。如一个客户端发一个字节,就就寝,该程序将堵塞在read()上,没法再为其他正当的客户端服务。办理办法:
1.非堵塞I/O
2.为每一个毗连创立历程或线程
3.对I/O操纵设置操时

4、经常使用函数
函数中均利用通用地点布局,以是一样平常要将特定协定的地点转换成通用地点布局。
1.从历程到内核
bind
connect
sendto
sendmsg

2.从内核到历程
Accept
Recvfrom
Recvmsg
Getpeername
Getsockname

3..剖析器函数:
ethostbyname
gethostbyaddr
getservbyname端标语是以收集字节序前往的
getservbyport参数port必需是收集字节序,以是要挪用htons(portnum)

4.I/O流和形貌字
fdopen():将形貌字(int)转换为I/O流(FILE*)
fileno():将I/O流转换为形貌字

注重:固然一个I/O流也是全双工的,可是读和写之间必需要有一些如fflush(),fseek(),fsetpos(),rewind()函数。最好的举措是对一个形貌字创立两个流,读和写分隔。

FILE*fin,*fout;
Fin=fdopen(sockfd,“r);
Fout=fdopen(sockfd,“w”);
Fgets(…);
Fputs(…);

可是这类尺度I/O库的编程必需注重以后的缓冲体例:
完整缓冲:只要缓冲区满、fflush()或历程exit()时才输入I/O行缓冲

5、僵尸历程
Zombie<defunct>历程:一个子历程停止,体系内核会收回SIGCHLD旌旗灯号,假如程序中没有效singal、sigaction举行SIG_IGN处置,也没有效wait、waitpid举行守候,停止的子历程就会变成僵尸历程。

僵尸历程发生的目标是保留子历程的信息,以便父历程在今后某个时候必要取回假如一个历程停止,但子历程有Zombie形态,这时候他们的父历程将由pid=1的init历程接受,用wait来守候卖力发出僵尸历程的资本。

僵尸历程占用内核空间

6、I/O形式
5个I/O形式:
1.堵塞I/O
2.非堵塞I/O
设置该标记代码:
intflags;
if((flags=fcntl(fd,F_GETFL,0))<0)
//堕落处置
flags|=O_NONBLOCK;
if((fcntl(fd,F_SETFL,flags))<0)
//堕落处置


封闭该标记代码:
…flags&=~O_NONBLOCK;


非堵塞connect的典范使用:
…//设置sockfd为非堵塞,如上述代码
if((n=connect(…))<0)
if(errno!=EINPROCESS)//一般情形下,connect毗连有必定工夫,应当前往EINPROCESS
return(-1);
if(n0)//特别情形,如CLIENT和SERVER在同台主机上,毗连疾速前往
gotodone;
FD_ZERO(&rset);
FD_SET(sockfd&rset);
West=rset;
Structtimevalval;
Val.tv_sec=…;
Val.tv_usec=0;
If((n=select(sockfd+1,&rset,&west,NULL,&val))0){//超时
Errno=ETIMEOUT;
Close(sockfd);
Return(-1);
}

interror;
if(FD_ISSET(sockfd,&rset)||FD_ISSET(sockfd,&west)){
len=sizeof(error);
if(getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&error,&len)<0)//反省SOCKET上待处置的毛病
return(-1);
}else
//堕落处置,暗示在这段工夫内没毗连上SERVER
done:
fcntl(sockfd,FD_SETFL,flags);//恢复为本来的形式
if(error){
close(sockfd);
errno=error;
return(-1);
}

return(0);


3.I/O复用
4.旌旗灯号驱动I/O(SIGIO)
5.异步I/O

前4个I/O形式都属于同步I/O,由于它们都堵塞于I/O的操纵(即I/O数据筹办好时,从内核空间往用户空间拷贝数据)

7、保卫历程
在背景运转而且与终端离开接洽的历程,只需体系一直止就一向运转着,有几种体例启动:
1./etc/rcx.d下的启动剧本
2.Inetd启动
3.Cron大概at启动

保卫历程的输入信息一样平常经由过程SYSLOG输入
函数示例:
#include<syslog.h>
#defineMAXFD64
voiddaemon_init()
{
intI;
pid_tpid;
if((pid=fork())!=0)
exit(0);
setsid():
signal(SIGHUP,SIG_IGN);
if((Pid=fork())!=0)
exit(0):
chdir(“/”);
umask(0);
for(i=0;i<MAXFD;i++)
close(i);
openlog(logname,LOG_PID,facility);
}


8、I/O超时
办法1:alarm()
比方:
staticvoidconnect_alarm(intsigno)
{
return;
}

signal(SIGALARM,connect_alarm);
if(alarm(timeout_sec)!=0
//error
if(connect(sockfd,(structsockaddr*)servaddr,servlen)<0)
{
close(sockfd);
if(errno=EINTR)
errno=ETIMEDOUT;
}

alarm(0);


办法2:select()
比方:
intreadable_timeout(intfd,intsec)
{
fd_setrset;
structtimevaltv;
FD_ZERO(&rset);
FD_SET(fd,&rset):
Tv.tv_sec=sec;
Tv.tv_usec=0;
Return(select(fd+1,&rset,NULL,NULL,&tv));
}

sendto(sockfd,…);
if(readable_timeout(sockfd,5)0)
//error
else
recvfrom(sockfd,…);//能够读



办法3:SO_RCVTIMEO和SO_SNDTIMEO套接口选项
比方:
structtimevaltv;
tv.tv_sec=5;
tv.tv_usec=0;
setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)):
while(fgets(sendline…)!=NULL){
sendto(sockfd,…);
n=recvfrom(sockfd,…);
if(n<0)
if(errnoEWOULEBLOCK){
fprintf(stderr,“socket,timeout”);
continue;
}
else
//error;



9、帮助数据的使用
能够使用于任何历程之间传送形貌字的使用sendmsg和recvmsg能够用来传送帮助数据(把持信息)。帮助数据由多少个帮助工具构成,每一个帮助工具由一个cmsghdr布局开首。
structmsghdr{
void*msg_name;//用于UDP协定,发送方能够寄存目标地点,吸收方能够寄存发送地点
size_tmsg_namelen;//同上
structiovec*msg_iov;//输出输入缓冲区数据,两个成员iov_base和iov_len
intmsg_iovlen;
void*msg_control;//帮助数据
size_tmsg_controllen;//帮助数据巨细
intmsg_flags;//只对recvmsg有效
};
Structcmsghdr{
Socklen_tcmsg_len;
Intcmsg_level;//IPV4是IPPROTO_IP,UNIX域是SOL_SOCKET
IntCmsg_type;//在IPV4中,IP_RECVDSTADDR承受UDP数据报的目标地点
//IP_RECVIF承受UDP数据报的接口索引
//UNIX域中是SCM_RIGHTS传送形貌字
//SCM_CREDS传送用户凭据
}

//charcmsg_data[];


msghdr.msg_control指向的帮助数据必需按cmsghdr布局对齐。使用UNIX域SOCKET体例:my_open(constchar*pathname,intmode)
{
intsockfd[2];

socketpair(AF_LOCAL,SOCK_STREAM,0,sockfd);//创立了一个流管道
if((childpid=fork())0)//子历程
close(socdfd[0]);
snprintf(argsockfd,sizeof(argsocdfd),“%d”,sockfd[1]);
snprintf(argmode,sizeof(mode),“%d”,mode);
execl(“./openfile”,“openfile”,argsockfd,pathname,argmode,(char*)NULL);
perror(“execerror
”);
}
close(sockfd[1]);

waitpid(chidpid,&status,0);
if(WIFEXITED(status)0)
perror(“chidprocessdidnotterminate
”);
if((status=WEXITSTATUS(status))0)//把停止形态转换为加入形态0-255
read_fd(sockfd[0],&c,1,&fd);
else{
errno=status;
fd=-1;
}
close(sockdf[0]);
return(fd);
}

ssize_tread_fd(intfd,void*ptr,ssize_tnbytes,int*recvfd)
{
structmsghdrmsg;//帮助数据工具
structioveciov[1];
union{
structcmsghdrunit;//这里界说帮助数据工具的目标是为了让msg_control缓冲区和帮助数据单位对齐,以是不是复杂地界说一个charcontrol[…],而是界说一个unioncharcontrol[CMSG_SPACE(sizeof(int))];//帮助数据缓冲区
}

control_buf;
structcmsghdr*unitptr;
intn;
msg.msg_control=control_buf.control;//帮助数据缓冲区
msg.msg_controllen=sizeof(control_buf.control);//帮助数据巨细
msg.msg_name=NULL;
msg.msg_namelen=0;
iov[0].iov_base=ptr;
iov[0].iov_len=nbytes;
msg.msg_iov=iov;
msg.msg_iovlen=1;
if((n=recvmsg(fd,&msg,0)<=0)
return(n);
if((unitptr=CMSG_FIRSTHDR(&msg)!=NULL&&unitptr->cmsg_len
CMSG_LEN(sizeof(int))){//cmsg_len应当=CMSG_LEN宏得出的了局
if(unitptr->cmsg_level!=SOL_SOCKET)//UNIXDOMAIN用SOL-SOCKET
//error
if(unitptr->cmsg_type!=SCM_RIGHTS)
//error
*recvd=*((int*)CMSG_DATA(unitptr));//取得该帮助工具的数据
}
else
*recvd=-1;
return(n);
}


子历程写程序摘录:
msg.msg_control=control_buf.control;
msg.msg_controllen=sizeof(control_buf.control);
unitprt=CMSG_FIRSTHDR(&msg);
unitptr->cmsg_len=CMSG_LEN(sizeof(int));
unitptr->cmsg_level=SOL_SOCKET;
unitptr->cmsg_level=SCM_RIGHTS;
*((int*)CMSG_DATA(unitptr))=sendfd;//CMSG_DATA()前往与cmsghdr相干联的数据的第一个字节的指针
msg.msg_name=NULL;
msg.msg_namelen=0;
iov[0].iov_base=ptr;
iov[0].iov_len=nbytes;
msg.msg_iov=iov;
msg.msg_iovlen=1;
sendmsg(fd,&msg,0);


用户凭据
#include<sys/ucred.h>
structfcred{
uid_tfc_ruid;//实在UID
gid_tfc_rgid;//实在GID
charfc_login[MAXLOGNAME];//LOGIN名字
uid_tfc_uid;//无效UID
shortfc_ngroups;//组数
gid_tfc_groups[NGROUPS];
}


#definefc_gidfc_groups[0];//无效GID
必要将LOCAL_CREDS这个SOCKET选项设置为1,在TCP中是CLIENT在毗连后第一次发送数据时由内核一同发送的,UDP是每次发送数据都发生
本章内容来自于互联网,小编只卖力排版,因受小编手艺所限,偶然断句的中央其实不正确,但小编已全力让本章收拾的更有可读性,请体谅。因小编保留这篇文章工夫太长,已记不清来历,以是未标注来历,敬请体谅!
我之所以想学。NET,是因为一直觉的BILLGATES好厉害,希望有一天能去微软,虽然现在还距离遥远,呵呵:)
精灵巫婆 该用户已被删除
沙发
发表于 2015-1-18 13:39:55 | 只看该作者
逐步缩小出错代码段的范围,最终确定错误代码的位置。
第二个灵魂 该用户已被删除
板凳
发表于 2015-1-25 16:06:37 | 只看该作者
主流网站开发语言之JSP:JSP和Servlet要放在一起讲,是因为它们都是Sun公司的J2EE(Java2platformEnterpriseEdition)应用体系中的一部分。
若天明 该用户已被删除
地板
发表于 2015-2-3 10:50:40 | 只看该作者
业务逻辑代码都不必做任何改动;继承性和多态性使得代码的可重用性大大提高,你可以通过继承已有的对象最大限度保护你以前的投资。并且C#和C++、Java一样提供了完善的调试/纠错体系。
海妖 该用户已被删除
5#
 楼主| 发表于 2015-2-8 20:30:25 | 只看该作者
能产生和执行动态、交互式、高效率的站占服务器的应用程序。运用ASP可将VBscript、javascript等脚本语言嵌入到HTML中,便可快速完成网站的应用程序,无需编译,可在服务器端直接执行。容易编写。
若相依 该用户已被删除
6#
发表于 2015-2-26 06:19:08 | 只看该作者
ASP.NET:ASP.net是Microsoft.net的一部分,作为战略产品,不仅仅是ActiveServerPage(ASP)的下一个版本;它还提供了一个统一的Web开发模型,其中包括开发人员生成企业级Web应用程序所需的各种服务。ASP.NET的语法在很大程度上与ASP兼容,同时它还提供一种新的编程模型和结构,可生成伸缩性和稳定性更好的应用程序,并提供更好的安全保护。
再现理想 该用户已被删除
7#
发表于 2015-3-8 12:47:59 | 只看该作者
asp.net空间的支持有:ASP.NET1.1/虚拟目录/MicrosoftFrontPage2000扩展/CDONTS,同时他的网站上也提供了Asp.net的使用详解和程序源代码,相信对使用ASP.NET编程的程序员来说会非常有用哦!
admin 该用户已被删除
8#
发表于 2015-3-16 01:30:45 | 只看该作者
虽然在形式上JSP和ASP或PHP看上去很相似——都可以被内嵌在HTML代码中。但是,它的执行方式和ASP或PHP完全不同。在JSP被执行的时候,JSP文件被JSP解释器(JSPParser)转换成Servlet代码,然后Servlet代码被Java编译器编译成.class字节文件,这样就由生成的Servlet来对客户端应答。所以,JSP可以看做是Servlet的脚本语言(ScriptLanguage)版。
9#
发表于 2015-3-22 19:00:42 | 只看该作者
Asp.net脚本的出现,为ASP空间带来了更高的稳定性,同时也为程序员建站提供更高环境!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2025-1-10 05:59

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表