您的位置:首页 > 理论基础 > 计算机网络

一起学习CC3200系列教程之TCP ECHO 服务端 selcet

2015-06-14 23:42 691 查看
一起学习CC3200系列教程之TCP ECHO 服务端 selcet



阿汤哥

序:

能力有限,难免有错,有问题请联系我,

QQ1519256298 hytga@163.com

Pdf下载http://pan.baidu.com/s/1hqiWB56

关键字:tcp 服务端 select 非阻塞

软件流程:创建一个tcp服务端,可以连接多个客户端,当客户端有数据发过来,就把数据原封不动地发回去。使用的是select机制。

select:软件阻塞于select函数,select可以用来判断有没有新的连接及新的数据通过这个select,可以实现非阻塞的读。

直接上源码:这是一个任务,所有的操作都在这里

void vTcpEchoServerUseSelect(void *pvParameters) {
SlSockAddrIn_t  xServer,xClient;

int szWatchList[mainWATCH_LIST_MAX];
int iSockFD,iMaxFD,iListenFD,iConnectFD;
int i,temp,iAddrSize,iRetVal,iRc;
SlSocklen_t xAddrLen;
char szBuf[200];
SlFdSet_t xFds;
struct SlTimeval_t tv;

tv.tv_sec = 20;
tv.tv_usec = 0;

//设置网络,
//为什么需要这里设置?
//因为本网络设置需要启动任务调度器:这个任务需要调度器去调度VStartSimpleLinkSpawnTask这个任务
//如果没有启动调度器,会导致wlan连不上。
WlanInit();

iAddrSize = sizeof(SlSockAddrIn_t);

UART_PRINT("\r\nvTcpEchoServerUseSelect\r\n");
//创建监听端口
iListenFD = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0);
if( iListenFD < 0 ){
//出错处理:略
UART_PRINT("\r\n sl_Socket \r\n");
}

//设置ip及端口信息
xServer.sin_family = SL_AF_INET;
xServer.sin_port = sl_Htons((unsigned short)9000);
xServer.sin_addr.s_addr = SL_INADDR_ANY;
iRetVal = sl_Bind(iListenFD,(SlSockAddr_t *) &xServer,sizeof(xServer));
if (iRetVal < 0 ) {
//出错处理:略
UART_PRINT("\r\n sl_Bind \r\n");
}
//创建监听,listen队列中等待的连接数为2
iRetVal = sl_Listen(iListenFD,10);
if (iRetVal < 0 ) {
//出错处理:略
UART_PRINT("\r\n sl_Listen \r\n");
}
for (i = 0;i < mainWATCH_LIST_MAX;i++){
//初始化监听的socket
szWatchList[i] = -1;
}
//设置监听的socket集的第一个为服务端的socket
szWatchList[0] = iListenFD;
iMaxFD = iListenFD;
while(1) {
//清除监听集合
SL_FD_ZERO(&xFds); //清空
//初始化监听集合,
for (i = 0 ;i < mainWATCH_LIST_MAX;i++) {

if (szWatchList[i] != -1) {
SL_FD_SET(szWatchList[i],&xFds);
}
}
UART_PRINT("\r\n start sl_Select \r\n");
//参数:socket句柄的最大值加1,可读的监听集合,可写的监听集合,出错的监听集合,溢出的时间
//select就是根据监听的集合去判断有哪些socket可读,可写。。
//首先我们把xFds看出一个集合而不是一个int,便于理解
//譬如,xfds 里面有1 ,2 ,3 ,4,
//当1可读,4可读
//函数返回后sfds里面有1,4
iRc = sl_Select(iMaxFD + 1,&xFds,0,0,&tv);

switch(iRc) {
case -1:
UART_PRINT("\r\n sl_Select \r\n");
break;
case 0:
UART_PRINT("\r\n 超过延时了 \r\n");
break;
default:
//判断服务端的sokcet有没有在监听的集合里
if (SL_FD_ISSET(iListenFD,&xFds)) {
//新的连接
UART_PRINT("iListenFD\r\n");
xAddrLen = sizeof(xClient);
//进行接受
iRetVal = sl_Accept(iListenFD,(struct SlSockAddr_t *)&xClient,&xAddrLen);
if (iRetVal < 0) {
UART_PRINT("\r\n sl_Accept \r\n");
} else {
for (i = 0 ;i < mainWATCH_LIST_MAX;i++) {
if (szWatchList[i] == -1) {
//存储socket句柄
szWatchList[i] = iRetVal;
UART_PRINT("\r\n 新的连接:%d:%d \r\n",i,szWatchList[i]);
break;
}
}
if ( i == mainWATCH_LIST_MAX) {
UART_PRINT("\r\n 请注意:太多连接了 \r\n");
} else {
if (iMaxFD < iRetVal) {
iMaxFD  = iRetVal;
}
}
}
}
{
for (i = 1 ;i < mainWATCH_LIST_MAX;i++) {

if (szWatchList[i] == -1) {
continue;
}
if (!SL_FD_ISSET(szWatchList[i],&xFds)){
continue;
}
//有数据可读
iRetVal = sl_Recv(szWatchList[i],szBuf,200,0);
if (iRetVal  <= 0 ) {
sl_Close(szWatchList[i]);
szWatchList[i] = -1;
//因为我们是在阻塞的模式下,连接关闭的时候,会读到0,
//所以我们就先直接关闭了。
UART_PRINT("\r\n sl_Recv %d \r\n",iRetVal);
} else {
iRetVal = sl_Send(szWatchList[i],szBuf,iRetVal,0);
if (iRetVal < 0) {
UART_PRINT("\r\n sl_Send \r\n");
}
}

}

}

}

}
}


宏定义

#define mainWATCH_LIST_MAX	(0x10)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: