0. 相關標頭檔
#
include <sys/socket.h>
#
include <netinet/in.h>
#
include <arpa/inet.h>#
include
<sys/epoll.h>
#
include <fcntl.h>#
include <unistd.h>#include <sys/time.h>#
include
<stdio.h>
#
include <stdlib.h>#
include <memory.h>#
include <assert.h>#
include <pthread.h>#
include
<errno.h>
1.socket初始化
s = socket(AF_INET, SOCK_DGRAM,
IPPROTO_UDP);
if(s == -1) return -1; s = socket(AF_INET,
SOCK_STREAM, IPPROTO_TCP);
if(s == -1) return -1;struct sockaddr_in
stAddr;
memset(&stAddr, 0, sizeof(stAddr));
stAddr.sin_family = AF_INET;
stAddr.sin_addr.s_addr = inet_addr(pszIp);
stAddr.sin_port = ntohs(ushPort);
if(bind(s, (struct
sockaddr*)&stAddr,
sizeof(stAddr)) ==
-1)
{
return -2;
} 2.非阻塞
//set non-blockingvoid setNonBlock( int sock_fd )
{
int opts;
opts =
fcntl( sock_fd, F_GETFL );
if( opts
< 0
)
{
printf("err:fcntl
F_GETFL");
exit( 1
);
}
opts = opts | O_NONBLOCK ;
if(
fcntl( sock_fd, F_SETFL, opts ) < 0 )
{
printf("err:fcntl F_SETFL");
exit( 1 );
}
}3.設定連接埠複用
使多個Socket對象綁定在同一個連接埠上 //set socket port reuse
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags)) == -1)
{
return -1;
}4.自訂各類緩衝大小
//reset recv buf len
if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&iRcvBufLen, sizeof(iRcvBufLen)) ==
-1)
{
return -1;
} //reset send buf len
if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&iSendBufLen, sizeof(iSendBufLen)) ==
-1)
{
return -1;
} 5.設定tcp nodelay( 關閉 Nagle演算法 )1) 在即時性要求較高時要關閉2) Nagle演算法用來減少少報文數目 int flag = 1;
int result =
setsockopt(sock, /* socket affected
*/
IPPROTO_TCP, /* set option at TCP level
*/
TCP_NODELAY, /* name of option
*/
(char *) &flag, /* the cast is
historical
cruft
*/
sizeof(int)); /* length of option
value */ 6.設定SO_LINGER 將linger參數設為一個正整數n時(n的值最大是65,535),在調用close方法後,將最多被阻塞n秒。在這n秒內,系統將盡量將未送出的資料包發送出去;如果超過了n秒,如果還有未發送的資料包,這些資料包將全部被丟棄;而close方法會立即返回。如果將linger設為0,和關閉SO_LINGER選項的作用是一樣的。 SO_LINGER選項用來改變此預設設定。使用如下結構:
struct linger {
int l_onoff; /* 0 = off, nozero
= on */
int l_linger; /* linger time */
};
struct linger so_linger;
so_linger.l_onoff = TRUE;
so_linger.l_linger =
30;
int result
=
setsockopt(s,
SOL_SOCKET,
SO_LINGER,
&so_linger,
sizeof
so_linger);
7.設定SO_KEEPALIVE 用戶端Socket每隔段的時間(大約兩個小時)就會利用閒置串連向伺服器發送一個資料包。這個資料包並沒有其它的作用,只是為了檢測一下伺服器是否仍處於活動狀態
keepAlive = 1;
setsockopt(listenfd, SOL_SOCKET, SO_KEEPALIVE,
(
void*)&keepAlive,
sizeof(keepAlive));
8.伺服器初始化
listen_fd = socket( AF_INET, SOCK_STREAM, 0);memset( &svrAddr, 0 ,
sizeof( sockaddr_in )
);
inet_aton( "127.0.0.1", &svrAddr.sin_addr );svrAddr.sin_family =
AF_INET;
svrAddr.sin_port = htons( 12345 );
int ret;
ret = bind( listen_fd, (sockaddr*)&svrAddr,
sizeof( sockaddr_in ) );
if( ret != 0 )
{
perror( "bind
fail" );
exit(-3);
}listen( listen_fd, 20 );
9. Accept
//一定要初始化長度,否則很容易accept出錯
clnLen = sizeof( sockaddr_in );
memset( &clnAddr, 0 , sizeof( sockaddr_in )
);conn_fd = accept( listen_fd, (sockaddr*)&clnAddr, &clnLen );
if(
conn_fd < 0
)
{
perror("conn_fd < 0");
break;
}