日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

js监听select值变化_网络编程——C++实现socket通信(TCP)高并发之select模式

發布時間:2025/4/5 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 js监听select值变化_网络编程——C++实现socket通信(TCP)高并发之select模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

相關函數:

服務端:

socket()

bind()

listen()

FD_ZERO()等輔助函數

select() 高并發select模式

accept()

read() 或 recv()等

write() 或 send()等

close()

客戶端:

socket()

connect()

write() 或 send()等

read() 或 recv()等

close()

著重說明下select函數及輔助函數用法說明。

調用select()函數之后,select()函數會清空它所檢測的socket描述符集合,所以每次調用select()之前都必須把socket描述符重新加入到待檢測的集合中。

int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);

-nfds: 監聽的最大文件描述符值+1

-readfds: 監聽socket可讀事件的集合的指針 (經常用到的)

-writefds: 監聽socket可寫事件的集合的指針

-execptfds:監聽socket異常事件的集合的指針

-timeout: 設置select監聽的超時時間,NULL表示阻塞監聽,0表示不阻塞立即返回,>0表示阻塞等待timeout時長

處理三個集合fd_set(實質是位圖)的輔助函數:

void FD_CLR(int fd, fd_set *set);//清除集合set中指定fd的位

int FD_ISSET(int fd, fd_set *set);//判斷set中指定fd的位是否為真(也就是fd是否在集合set中)

void FD_SET(int fd, fd_set *set);//設置集合set中指定fd的位

void FD_ZERO(fd_set *set);//清空集合set

注意:每當服務端連接斷開后,進入TIME_WAIT狀態,等待2msl時間之后才能重新使用IP和端口,否則在bind時就會報錯。要解決這個問題可以在程序開始時調用端口復用函數setsockopt。原型如下:

//int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);

/* sockfd:標識一個套接口的描述字。

   level:選項定義的層次;支持SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6。

   optname:需設置的選項。

   optval:指針,指向存放選項值的緩沖區

   optlen:optval緩沖區長度。

   返回值: 成功返回0,失敗返回 -1. */

實際調用:

setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

廢話不多說,上源碼!

實現的功能:客戶端C向服務端S發送一串字符數據,S端會對字符串做轉大寫操作然后回發給C端。直接在咱們Tcp_Server.cpp基礎上修改代碼

服務端Select_Server.cpp

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include //select() 頭文件

#define MAXSIZE 1024

#define IP_ADDR "127.0.0.1"

#define IP_PORT 8888

int main()

{

int i_listenfd, i_connfd;

struct sockaddr_in st_sersock;

char msg[MAXSIZE];

int nrecvSize = 0;

int maxfd = -1;//記錄最大fd

fd_set readfds;

int allfds[MAXSIZE];//存放當前所有可用的fd的數組

int index = 0;//記錄fd數組中最大fd對應的下標

for(i : allfds)

{

i = -1;

}

if((i_listenfd = socket(AF_INET, SOCK_STREAM, 0) ) < 0)//建立socket套接字

{

printf("socket Error: %s (errno: %d)", strerror(errno), errno);

exit(0);

}

memset(&st_sersock, 0, sizeof(st_sersock));

st_sersock.sin_family = AF_INET; //IPv4協議

st_sersock.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY轉換過來就是0.0.0.0,泛指本機的意思,也就是表示本機的所有IP,因為有些機子不止一塊網卡,多網卡的情況下,這個就表示所有網卡ip地址的意思。

st_sersock.sin_port = htons(IP_PORT);

if(bind(i_listenfd,(struct sockaddr*)&st_sersock, sizeof(st_sersock)) < 0) //將套接字綁定IP和端口用于監聽

{

printf("bind Error: %s (errno: %d)", strerror(errno), errno);

exit(0);

}

if(listen(i_listenfd, 20) < 0)//設定可同時排隊的客戶端最大連接個數

{

printf("listen Error: %s (errno: %d)", strerror(errno), errno);

exit(0);

}

allfds[index] = maxfd = i_listenfd;//先賦值

printf("======waiting for client's request======");

//準備接受客戶端連接

while(1)

{

FD_ZERO(&readfds);

for(int i = 0; i<= index; i++)

{

FD_SET(allfds[i], &readfds);//加入可讀事件集合中

printf("----------allfds中的元素allfds[%d]:%d", i, allfds[i]);

}

int nCount = select(maxfd+1, &readfds, NULL, NULL, NULL);//select,返回共監聽到有多少個fd上有事件

printf("----------select監聽到可讀事件計數:%d",nCount);

for(int i = 0; i < MAXSIZE; i++)

{

if(nCount == 0)

{

break;

}

if(!FD_ISSET(allfds[i], &readfds))

{

continue;//不在監聽事件中則跳過

}

printf("----------即將處理監聽到的 allfds[%d]: %d", i, allfds[i]);

if(allfds[i] == i_listenfd)//監聽到有客戶端連接

{

nCount--;

if((i_connfd = accept(i_listenfd, (struct sockaddr*)NULL, NULL)) < 0)//阻塞等待客戶端連接

{

printf("accept Error: %s (errno: %d)", strerror(errno), errno);

//continue;

}

else

{

printf("Client[%d], welcome!", i_connfd);

}

for(int n = 0; n < MAXSIZE; n++)

{

if(allfds[n] == -1)//將新客戶端fd加入數組中

{

allfds[n] = i_connfd;

maxfd < i_connfd ? maxfd = i_connfd : true ;

index < n ? index = n : true ;

printf("將新客戶端fd加入數組中. fd:%d, maxfd:%d, index:%d", allfds[n], maxfd, index);

break;

}

}

}

else//監聽到已連接的客戶端發來的數據

{

nCount--;

//接受客戶端發來的消息并作處理(小寫轉大寫)后回寫給客戶端

memset(msg, 0 ,sizeof(msg));

if((nrecvSize = read(allfds[i], msg, MAXSIZE)) < 0)

{

printf("accept Error: %s (errno: %d)", strerror(errno), errno);

continue;

}

else if( nrecvSize == 0)//read返回0代表對方已close斷開連接。

{

printf("client has disconnected!");

if(maxfd == allfds[i])

{

maxfd--;

}

if(index == i)

{

index--;

}

close(allfds[i]); //

FD_CLR(allfds[i], &readfds);//清除readfds中對它的監聽事件

allfds[i] = -1;//清除數組中相應位置

continue;

}

else

{

printf("recvMsg:%s", msg);

for(int i=0; msg[i] != '0'; i++)

{

msg[i] = toupper(msg[i]);

}

if(write(allfds[i], msg, strlen(msg)+1) < 0)

{

printf("accept Error: %s (errno: %d)", strerror(errno), errno);

}

}

}

}

}//while

close(i_listenfd);

return 0;

}

客戶端Select_Client.cpp (直接用咱們Tcp_Client.cpp就可以)

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define MAXSIZE 1024

#define IP_ADDR "127.0.0.1"

#define IP_PORT 8888

int i_sockfd = -1;

void SigCatch(int sigNum)//信號捕捉函數(捕獲Ctrl+C)

{

if(i_sockfd != -1)

{

close(i_sockfd);

}

printf("Bye~! Will Exit...");

exit(0);

}

int main()

{

struct sockaddr_in st_clnsock;

char msg[1024];

int nrecvSize = 0;

signal(SIGINT, SigCatch);//注冊信號捕獲函數

if((i_sockfd = socket(AF_INET, SOCK_STREAM, 0) ) < 0)//建立套接字

{

printf("socket Error: %s (errno: %d)", strerror(errno), errno);

exit(0);

}

memset(&st_clnsock, 0, sizeof(st_clnsock));

st_clnsock.sin_family = AF_INET; //IPv4協議

//IP地址轉換(直接可以從物理字節序的點分十進制 轉換成網絡字節序)

if(inet_pton(AF_INET, IP_ADDR, &st_clnsock.sin_addr) <= 0)

{

printf("inet_pton Error: %s (errno: %d)", strerror(errno), errno);

exit(0);

}

st_clnsock.sin_port = htons(IP_PORT);//端口轉換(物理字節序到網絡字節序)

if(connect(i_sockfd, (struct sockaddr*)&st_clnsock, sizeof(st_clnsock)) < 0)//主動向設置的IP和端口號的服務端發出連接

{

printf("connect Error: %s (errno: %d)", strerror(errno), errno);

exit(0);

}

printf("======connect to server, sent data======");

while(1)//循環輸入,向服務端發送數據并接受服務端返回的數據

{

fgets(msg, MAXSIZE, stdin);

printf("will send: %s", msg);

if(write(i_sockfd, msg, MAXSIZE) < 0)//發送數據

{

printf("write Error: %s (errno: %d)", strerror(errno), errno);

exit(0);

}

memset(msg, 0, sizeof(msg));

if((nrecvSize = read(i_sockfd, msg, MAXSIZE)) < 0)//接受數據

{

printf("read Error: %s (errno: %d)", strerror(errno), errno);

}

else if(nrecvSize == 0)

{

printf("Service Close!");

}

else

{

printf("Server return: %s", msg);

}

}

return 0;

}

總結

以上是生活随笔為你收集整理的js监听select值变化_网络编程——C++实现socket通信(TCP)高并发之select模式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。