多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > 服務器如何給多個客戶端分配端口號

服務器如何給多個客戶端分配端口號

來源:程序員人生   發布時間:2014-12-15 09:13:13 閱讀次數:6170次

在1臺計算機上,使用socket通訊時,不同進程辨別網絡通訊的連接依托3個參數:通訊所用協議、地址IP、端口號。

服務器端來講,通過bind、listen,以后accept建立新的連接,accept返回新連接的句柄,這樣就建立了1條連接。那末新建立的連接使用的端口號是不是和listen所用端口號相同呢?之前我1直以為服務器會隨機分配1個新的端口號來使用,后來發現錯了。

由于1、現在使用多路IO復用epoll等,配置好點的服務器可以支持數10萬個并發連接,端口號為16位,最多才2^16⑴,且加上1些經常使用的端口號不能使用,可用的端口號都沒那末多。2、現在服務器大多使用防火墻,防火墻只對特定端口開放。如果accept隨機分配端口號,會不能通過防火墻。

TCP/IP協議中,IP協議是端到真個協議,它只是負責把把數據發送到端,交付給上層而已。運輸層TCP、UDP加上了端口號,目的是辨別不同的利用。其中TCP還實現了流量控制、可靠傳輸等,而UDP只是應當是沒有對IP層數據進行處理了。

在以往的知識中,我知道1個利用程序只能使用1個端口號,如果accept返回的句柄還是使用listen的端口號,那末怎樣實現通訊呢?如果建立多個連接,利用程序怎樣區收到的信息來自哪一個客戶端呢?

現在才理解到accept返回的句柄建立的連接包括4部份:源IP、源端口號、目的IP、目的端口號。這樣在1個利用程序中,就算和多個客戶端建立連接,在收到數據后,利用程序通過目的IP和目的端口號也能辨別是哪1條連接。

通過1個echo服務器來驗證1下,client和server都在同1臺機器上:

服務器監聽8000端口,在未建立連接時,可以看到在監聽8000


在通過1個客戶端建立連接后,可以看到建立了1條連接,服務器真個端口號是8000,監聽的還是8000。


在連接1個客戶端,可以看到建立了兩條連接,服務器端都是使用8000,監聽的還是8000。


下面是server端代碼:

#include<stdio.h> #include<sys/socket.h> #include<unistd.h> #include<errno.h> #include<netinet/in.h> void str_echo(int sockfd) { int n; char buf[1024]; again: while((n=read(sockfd,buf,1024))>0) { write(sockfd,buf,n); } if(n<0&&errno==EINTR) goto again; else if(n<0) printf("str_error:read error"); } int main(int argc, char **argv) { int listenfd, connfd; pid_t childid; socklen_t clilen; struct sockaddr_in cliaddr, servaddr; listenfd=socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family=AF_INET; servaddr.sin_addr.s_addr=htonl(INADDR_ANY);//host IP servaddr.sin_port=htons(8000);//port bind(listenfd,(struct sockaddr*)&servaddr,sizeof(struct sockaddr)); listen(listenfd,5);//最多處理5個監聽 for(;;) { clilen=sizeof(cliaddr); //進場阻塞在accept上 connfd=accept(listenfd, (struct sockaddr*)&cliaddr,&clilen); if(childid=fork()==0)//child { close(listenfd);//在子進程中關閉監聽 str_echo(connfd);//處理監聽的連接 exit(0); } } close(listenfd); }

客戶端代碼:

#include<stdio.h> #include<sys/socket.h> #include<netinet/in.h> #include<unistd.h> void str_cli(FILE *fp, int sockfd) { char sendline[1024],recvline[1024]; while(fgets(sendline, 1024, fp)!=NULL) { //發給Server write(sockfd,sendline,sizeof(sendline)); //讀Server if(read(sockfd,recvline,1024)==0) { printf("str_cli:server terminated prematurely "); exit(0); } //fputs(recvline,stdout); printf("%s",recvline); } } int main(int argc, char **argv) { int sockfd; struct sockaddr_in servaddr; if(argc!=2) { printf("usage:client IPaddress "); exit(0); } sockfd=socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family=AF_INET; servaddr.sin_port=htons(8000); //把輸入的IP存到sin_addr中 inet_pton(AF_INET,argv[1],&servaddr.sin_addr); printf("server IP:%s ",argv[1]); //建立連接 connect(sockfd,(struct sockaddr*)&servaddr,sizeof(struct sockaddr)); str_cli(stdin,sockfd); exit(0); }


生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 一级a性色生活片毛片 | 免费爱做网站在线看 | 国产永久高清免费动作片www | 欧美freesex呦交6_10 | 国产一区二区视频在线观看 | 亚洲福利视频一区 | 亚洲欧洲日韩国产 | 日韩欧美毛片免费观看视频 | 欧美人成在线观看ccc36 | 成人亚洲精品一区二区 | free性video18 | 欧美xxxx做受欧美gay | 欧美成人手机视频免费播放 | 极品福利在线 | 久久久久免费精品国产 | 狂野欧美性猛交xxxx免费按摩 | 国产欧美另类久久久精品免费 | 日韩精品中文字幕久久 | 亚洲成年人在线 | 亚洲人成网站在线观看播放 | 一区福利视频 | 国产一区二区三区在线免费 | 亚洲 欧美 日韩在线 | 国产乱人乱精一区二区视频密 | 亚洲成人在线免费观看 | 一区二区三区中文字幕 | 欧美成人午夜视频在线观看 | 老司机午夜性大片免费 | 日本一区二区不卡在线 | 亚洲十八精品网站 | 激情综合五月天丁香婷婷 | 亚洲第一色站 | 亚洲色图欧美 | 夜夜未满十八勿进的爽爽影院 | 久久国产综合 | 一区二区三区在线视频播放 | 久久精品免费看 | 久久另类 | h在线网站 | 午夜久久久久久亚洲国产精品 | 韩国av片永久免费 |