NET网页编程之Socket编程(一)
我之所以想学。NET,是因为一直觉的BILLGATES好厉害,希望有一天能去微软,虽然现在还距离遥远,呵呵:)1、基础常识主机字节序和收集字节序
主机字节序即内存中存储字节的办法有:
1.Littleendian:将低序字节存储在肇端地点
2.Bigendian:将高序字节存储在肇端地点
收集字序暗示收集协定在处置多字节时的按次,一概为bigendian
主机字节序和收集字节序转换的函数:
#include<netinet/in.h>
uint16_thtons(uint16_t<16位的主机字节序>)
uint32_thtonsl(uint32_t<32位的主机字节序>)//转换为收集字节序
uint16_tntohs(uint16_t<16位的收集字节序>)
uint32_tntohl(uint32_t<32位的收集字节序>)//转换为主机字节序
缓冲区
每一个TCPSOCKET有一个发送缓冲区和一个吸收缓冲区,TCP具有流量把持,以是吸收缓冲区]的巨细就是关照另外一真个窗口的巨细,对方不会发年夜于该窗口巨细的数据;而UDPSOCKET只要一个吸收缓冲区无流量把持,当吸收的数据报溢出时就会被抛弃
通讯域(地点族)
套接字存在于特定的通讯域(即地点族)中,只要从属于统一地点族的套接字才干创建对话。Linux撑持AF_INET(IPv4协定)、AF_INET6(IPv6协定)和AF_LOCAL(Unix域协定)。
套接口(socket)=收集地点+端标语。,要创建一个套接口必需挪用socket函数,套接口有三品种型,即字撙节套接口(SOCK_STREAM),数据报套接口(SOCK_DGRAM)和原始套接口(SOCK_RAW)。界说一个毗连的一个端点的两元组,即IP地点和端标语,称为一个套接口。
在收集毗连中,两个端点所构成的四元组(即当地IP、当地PORT、远程IP和远程PORT)称为socketpair,该四元组独一的标识了一个收集毗连。该情形可经由过程netstat考证。
2、socket地点布局
1.IPv4的Socket地点布局(定长)
Structin_addr{
In_addr_ts_addr;//32位IP地点,收集字节序
}
Structsockaddr_in{
Uint8_tsin_len;//IPv4为流动的16字节长度
Sa_family_tsin_family;//地点簇范例,为AF_INET
In_port_tsin_port;//16位端标语,收集字节序
Structin_addrsin_addr;//32位IP地点
Charsin_zero;//未用
}
2.IPv6的socket地点布局(定长)
structin6_addr{
uint8_ts6_addr;//128位IP地点,收集字节序
}
structsockaddr_in6{
uint8_tsin6_len;//IPv6为流动的24字节长度
sa_family_tsin6_family;//地点簇范例,为AF_INET6
in_port_tsin6_port;//16位端标语,收集字节序
uint32_tsin6_flowinfo;//32位流标签
structin6_addrsin6_addr;//128位IP地点
}
3.UNIX域socket地点布局(变长)
Structsockaddr_un,地点簇范例为AF_LOCAL
4.数据链路socket地点布局(变长)
structsockaddr_dl,地点簇范例为AF_LINK
5.通用的socket地点布局
structsockaddr{
uint8_tsa_len;
sa_family_tsa_family;
charsa_data;
}
3、C/S收集编程
初始化sock毗连符:
intsocket(intdomain,inttype,intprotocol);
函数前往socket形貌符,前往-1暗示堕落
domain参数只能取AF_INET,protocol参数一样平常取0
使用示例:
TCP体例:sockfd=socket(AF_INET,SOCK_STREAM,0);
UDP体例:sockfd=socket(AF_INET,SOCK_DGRAM,0);
绑定端口:
intbind(intsockfd,structsockaddr*sa,intaddrlen);
函数前往-1暗示堕落,最多见的毛病是该端口已被其他程序绑定。
必要注重的一点:在Linux体系中,1024以下的端口只要具有root权限的程序才干绑定.
毗连收集(用于TCP体例):
intconnect(intsockfd,structsockaddr*servaddr,intaddrlen);
函数前往-1暗示堕落,多是毗连超时或没法会见。前往0暗示毗连乐成,能够经由过程sockfd传输数据了。
监听端口(用于TCP体例):
intlisten(intsockfd,intqueue_length);
必要在此前挪用bind()函数将sockfd绑定到一个端口上,不然由体系指定一个随机的端口。
吸收行列:一个新的Client的毗连哀求先被放在吸收行列中,直到Server程序挪用accept函数承受毗连哀求。
第二个参数queue_length,指的就是吸收行列的长度也就是在Server程序挪用accept函数之前最年夜同意的毗连哀求数,过剩的毗连哀求将被回绝。
呼应毗连哀求(用于TCP体例):
intaccept(intsockfd,structsockaddr*addr,int*addrlen);
accept()函数将呼应毗连哀求,创建毗连并发生一个新的socket形貌符来形貌该毗连,该毗连用来与特定的Client互换信息。
函数前往新的毗连的socket形貌符,毛病前往-1
addr将在函数挪用后被填进毗连对方的地点信息,如对方的IP、端口等。
addrlen作为参数暗示addr内存区的巨细,在函数前往后将被填进前往的addr布局的巨细。
accept缺省是堵塞函数,堵塞直到有毗连哀求
使用示例:
structsockaddr_intheir_addr;/*用于存储毗连对方的地点信息*/
intsin_size=sizeof(structsockaddr_in);
……(顺次挪用socket(),bind(),listen()等函数)
new_fd=accept(sockfd,&their_addr,&sin_size);
printf(”对方地点:%s
",inet_ntoa(their_addr.sin_addr));
……
封闭socket毗连:
intclose(intsockfd);
封闭毗连将中止对该socket的读写操纵。
封闭用于listen()的socket形貌符将克制其他Client的毗连哀求。
部分封闭socket毗连:
intshutdown(intsockfd,inthow);
Shutdown()函数能够片面的中止毗连,即克制某个偏向的信息传送。
参数how的意义:
0-克制吸收信息
1-克制发送信息
2-吸收和发送都被克制,与close()函数效果不异
socket轮询选择:
intselect(intnumfds,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,structtimeval*timeout);
使用于多路同步I/O形式(将在同步事情形式中具体解说)
FD_ZERO(*set)清空socket汇合
FD_SET(s,*set)将s到场socket汇合
FD_CLR(s,*set)从socket汇合往失落s
FD_ISSET(s,*set)判别s是不是在socket汇合中
常数FD_SETSIZE:汇合元素的最多个数
守候选择机制:
intpoll(structpollfd*ufds,unsignedintnfds,inttimeout);
是select机制的一个变种,使用于多路同步I/O形式(将在同步事情形式中具体解说)
ufds是pollfd布局的数组,数组元素个数为nfds。
structpollfd{
intfd;/*文件形貌字*/
shortevents;/*哀求事务汇合*/
shortrevents;/*前往工夫汇合*/
};
吸收/发送动静:
TCP体例:
intsend(ints,constvoid*buf,intlen,intflags);
intrecv(ints,void*buf,intlen,intflags);
函数前往实践发送/吸收的字节数,前往-1暗示堕落,必要封闭此毗连。
函数缺省是堵塞函数,直到发送/吸收终了或堕落
注重:假如send函数前往值与参数len不相称,则残剩的未发送信息必要再次发送
UDP体例:
intsendto(ints,constvoid*buf,intlen,intflags,conststructsockaddr*to,inttolen);
intrecvfrom(ints,void*buf,intlen,intflags,structsockaddr*from,int*fromlen);
与TCP体例的区分:
必要指定发送/吸收数据的对方(第五个参数to/from)
函数前往实践发送/吸收的字节数,前往-1暗示堕落。
函数缺省是堵塞函数,直到发送/吸收终了或堕落。
注重:假如send函数前往值与参数len不相称,则残剩的未发送信息必要再次发送
注重,收集字撙节的读写分歧于文件的读写,因为socket缓冲的要素,大概读写的字节数小于所指定的字节数。以是可使用以下函数:
ssize_treadn(intfd,void*buf,size_tn)
{
ssize_tnleft;
ssize_tnread;
char*ptr;
ptr=buf;
nleft=n;
while(nleft>0)
{
if((nread=read(fd,ptr,nleft))<0){
if(errnoEINTR)
nread=0;
else
return(-1);
}
elseif(nread0)//EOF
break;
nleft-=nread;
ptr+=nread;
}
return(n-nleft);
}
ssize_twritten(intfd,constvoid*buf,size_tn)
{
ssize_tnleft;
ssize_tnwrite;
constchar*ptr;
ptr=buf;
nleft=n;
while(nleft>0){
if(nwrite=write(fd,ptr,left)<=0){
if(errnoEINTR){
nwrite=0;
else
return(-1);
}
nleft-=nwrite;
ptr+=nwrite;
}
return(n);
}
基于动静的体例:
intsendmsg(ints,conststructmsghdr*msg,intflags);
intrecvmsg(ints,structmsghdr*msg,intflags);
标记位:
下面这六个发送/吸收函数均有一个参数flags,用来指明数据发送/吸收的标记,经常使用的标记次要有:
MSG_PEEK对数据吸收函数无效,暗示读出收集数据后不扫除已读的数据
MSG_WAITALL对数据吸收函数无效,暗示一向实行直到buf读满、socket堕落大概程序收到旌旗灯号。
MSG_DONTWAIT对数据发送函数无效,暗示不堵塞守候数据发送完后前往,而是间接前往。
(只对非堵塞socket无效)
MSG_NOSIGNAL对发送吸收函数无效,暗示在对方封闭毗连后堕落但不发送SIGPIPE旌旗灯号给程序。
MSG_OOB对发送吸收都无效,暗示读/写带外数据(out-of-banddata)
IP地点字符串和收集字节序的二进制IP地点互相转换的函数:
#inlcude<arpa/inet.h>
intinet_aton(constchar*<IP地点字符串>,structin_addr*<32位的收集字节序情势的IP地点>)
乐成—1
失利—0
[通用地点函数]intinet_pton(int<地点簇范例>,能够是AF_INET/AF_INET6>,constchar
*<IP地点字符串>,void*<32位的收集字节序情势的IP地点>)
乐成—1
格局毛病—0
失利—0
in_addr_tinet_addr(constchar*<IP地点字符串>)前往32位收集字节序的IP地点,失利—INADDR_NONE
char*inet_ntoa(structin_addr<32位的收集字节序情势的IP地点>)前往IP地点字符串
constchar*inet_ntop(int<地点簇范例>,constvoid*<32位的收集字节序情势的IP地点>,char*<IP地点字符串>,size_t<IP地点字符串的最年夜长度>)
前往指向了局<IP地点字符串>的指针
字节按次转换
htons()--"HosttoNetworkShort"
htonl()--"HosttoNetworkLong"
ntohs()--"NetworktoHostShort"
ntohl()--"NetworktoHostLong"
毗连历程是经由过程一系列形态暗示的,这些形态有:LISTEN,SYN-SENT,SYN-RECEIVED,ESTABLISHED,FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT和CLOSED。CLOSED暗示没有毗连,各个形态的意义以下:
LISTEN-侦听来自远方TCP端口的毗连哀求;
SYN-SENT-在发送毗连哀求后守候婚配的毗连哀求;
SYN-RECEIVED-在收到和发送一个毗连哀求后守候对毗连哀求切实其实认;
ESTABLISHED-代表一个翻开的毗连,数据能够传送给用户;
FIN-WAIT-1-守候远程TCP的毗连中止哀求,或先前的毗连中止哀求切实其实认;
FIN-WAIT-2-从远程TCP守候毗连中止哀求;
CLOSE-WAIT-守候从当地用户发来的毗连中止哀求;
CLOSING-守候远程TCP对毗连中止切实其实认;
LAST-ACK-守候本来发向远程TCP的毗连中止哀求切实其实认;
TIME-WAIT-守候充足的工夫以确保远程TCP吸收到毗连中止哀求切实其实认;
CLOSED-没有任何毗连形态;
一个tcp协定的socket编程例子:
/*主函数*/
intlistenfd,connfd;
structsockaddr_inservaddr,cliaddr;
structhostent*hp;
structservent*sp;
structin_addr**pptr;
if((hp=gethostbyname(argv))NULL)//error
if((sp=getservbyname(argv,“tcp”))NULL)//error
pptr=(structin_addr**)hp->h_addr_list;
listenfd=socket(AF_INET,SOCK_STREAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;//servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
memcpy(&servaddr.sin_addr,*pptr,sizeof(structin_addr));
servaddr.sin_port=htons(portnum);
bind(listenfd,(structsockaddr*)&servaddr,sizeof(servaddr));
listen(listenfd,listenqueuenum);
signal(SIGCHLD,sig_chld);
for(;;)
{
len=sizeof(cliaddr);
if((connfd=accept(listenfd,(structsockaddr*)&cliaddr,&len))<0){
if(errornoEINTR)
continue;
else
perror(“accepterror”);
}
if(fork()0)//子历程,复制父历程的一切形貌字,以是listenfd和connfd被父子历程所共享,形貌字的会见记数值都累计为2
{
close(listenfd);
printf(“connectionfrom%s,port%d
”,inet_ntop(AF_INET,&cliaddr,.sin_addr,buf,sizeof(buf)),ntohs(cliaddr.sin_port));
snprintf(buf,……);
write(connfd,buf,strlen(buf));
…//process
close(connfd);//处置停止后封闭socket毗连
exit(0);//子历程加入
}
close(connfd);//父历程用不到connfd,能够将其封闭,因为形貌字的会见记数值由2减1,不会触发FIN分节,(和shundown分歧)只要为0时,才真正封闭毗连
}
自选端口应当年夜于1023(不如果保存端口),小于49152(一时端口)本章内容来自于互联网,小编只卖力排版,因受小编手艺所限,偶然断句的中央其实不正确,但小编已全力让本章收拾的更有可读性,请体谅。因小编保留这篇文章工夫太长,已记不清来历,以是未标注来历,敬请体谅!
你觉得数据库怎么样? 以上是语言本身的弱点,在功能方面ASP同样存在问题,第一是功能太弱,一些底层操作只能通过组件来完成,在这点上是远远比不上PHP/JSP,其次就是缺乏完善的纠错/调试功能,这点上ASP/PHP/JSP差不多。 业务逻辑代码都不必做任何改动;继承性和多态性使得代码的可重用性大大提高,你可以通过继承已有的对象最大限度保护你以前的投资。并且C#和C++、Java一样提供了完善的调试/纠错体系。 能产生和执行动态、交互式、高效率的站占服务器的应用程序。运用ASP可将VBscript、javascript等脚本语言嵌入到HTML中,便可快速完成网站的应用程序,无需编译,可在服务器端直接执行。容易编写。 ASP.Net摆脱了以前ASP使用脚本语言来编程的缺点,理论上可以使用任何编程语言包括C++,VB,JS等等,当然,最合适的编程语言还是MS为.NetFrmaework专门推出的C(读csharp)。 现在的ASP.net分为两个版本:1.1和2.0Asp.net1.1用VS2003(visualstudio2003)编程。Asp.net2.0用VS2005(visualstudio2005)编程。现在一般开发用的是VS2003。 ASP在执行的时候,是由IIS调用程序引擎,解释执行嵌在HTML中的ASP代码,最终将结果和原来的HTML一同送往客户端。 众所周知,Windows以易用而出名,也因此占据不少的服务器市场。 业务逻辑代码都不必做任何改动;继承性和多态性使得代码的可重用性大大提高,你可以通过继承已有的对象最大限度保护你以前的投资。并且C#和C++、Java一样提供了完善的调试/纠错体系。
页:
[1]