LINUX C 进行TCP网络连接,怎样设置连接超时时间

LINUX C 进行TCP网络连接,怎样设置连接超时时间,第1张

如果你确定,真的不需要等这么久,或者用户希望可以随时中上连接过程,那么一般是用 非阻塞模式来做的. 看看我的这段连接代码(节选),可以作为TCP连接的典范:

bool CRemoteLink::Connect()

{

OnDisconnected() // 如果已经连接,则断开

if(!m_bUseProxy)

{

m_iConnStatus = SS_CONNECTING // 正在连接状态

GNTRACE ("开始连接到远程服务器[%s][%ld]...\n", m_strip.c_str(), m_port)

// 建立套接字, 准备连接到服务器

m_socket = ::socket(AF_INET, SOCK_STREAM, 0)

if (socket <0) {

if(m_pCallBack)

m_pCallBack->OnSocketError(SE_CREATE, MSG_SE_CREATE)

return false

}

// 设为异步 *** 作方式

unsigned long on = 1

if (::ioctlsocket(m_socket, FIONBIO, &on) <0) {

::closesocket(m_socket)

if(m_pCallBack)

m_pCallBack->OnSocketError(SE_CREATE, MSG_SE_CREATE)

return false

}

sockaddr_in addr

memset(&addr, 0, sizeof(addr))

addr.sin_family = AF_INET

addr.sin_addr.s_addr = inet_addr(m_strip.c_str())

addr.sin_port = htons(m_port)

int rt

rt = ::connect(m_socket, (sockaddr *) &addr, sizeof(addr))

if (rt == 0) {

OnConnected()

return true

}

// ==================================================================

timeval to

// 首先建立连接

fd_set wfds

fd_set efds

FD_ZERO(&wfds)

FD_ZERO(&efds)

// test shutdown event each 100ms.

to.tv_sec = 0

// CONNECT_TIMEOUT

to.tv_usec = 100000

int it = 0

while(!m_meShutdown.Wait(0) &&!m_meConnStop.Wait(0))

{

FD_SET(m_socket, &wfds)

FD_SET(m_socket, &efds)

int n = select(m_socket + 1, NULL, &wfds, &efds, &to)

if (n >0) {

if(FD_ISSET(m_socket, &wfds))

{

OnConnected()

return true

}

else

{

//int err = ::WSAGetLastError()

//const char* msg = GetLastErrorMessage(err)

GNTRACE ("CRemoteLink::Connect : connection attempt failed!\n")

if(m_pCallBack)

m_pCallBack->OnSocketError(SE_CONN, MSG_SE_CONN)

break

}

} else if (n <0) { // Select Error

int err = ::WSAGetLastError()

const char* msg = GetLastErrorMessage(err)

GNTRACE ("CRemoteLink::Connect : Select Error.[%d] - %s\n", err, msg)

if(m_pCallBack)

m_pCallBack->OnSocketError(err, msg)

break

}

else

{

it += 100

if(it >30000) // 连接超时 -- (30S)

{

GNTRACE ("CRemoteLink::Connect : Time out.\n")

if(m_pCallBack)

m_pCallBack->OnSocketError(SE_TIMEOUT, MSG_SE_TIMEOUT)

break

}

}

}

if(m_meConnStop.Wait(0))

{

GNTRACE("连接过程进行时被取消。\n")

}

}

else

{

// 通过代理服务器连接

那就必须要精通 Linux 的网络协议的 socket 编程了。这个肯定是可以检测网络状态的。具体的 server/client 编程模式,可以参考《TCP/IP 协议详解》一书(上、下册)。

unsigned int dir(char * server) {

int sck//套接字变量

struct sockaddr_in serv_adr//远程主机的地址

struct hostent *host //指向远程主机的指针

unsigned char databuf[FILEBUF_SIZE]//数据

int bytes = 0, bytesread = 0//字节数,读取到的字节数

host = gethostbyname(server)//根据远程主机的主机名,得到指向远程主机的指针

if (host == (struct hostent *) NULL) { //如果得到指向远程主机的指针失败,报告错误,并返回

perror("gethostbyname failed")

return 0

}memset(&serv_adr, 0, sizeof(serv_adr))//初始化远程主机的地址,结构体内所有成员清零

serv_adr.sin_family = AF_INET //设置地址类型

memcpy(&serv_adr.sin_addr, host->h_addr, host->h_length)//取出指向远程主机的指针中包含的地址信息,赋给远程主机地址变量

serv_adr.sin_port = htons(SERVICE_PORT)//设置端口号,比如http服务对应80端口,ftp对应21端口

if ((sck = socket(AF_INET, SOCK_STREAM, 0)) <0) { //如果建立TCP协议的套接字失败,报告错误,并返回

perror("error on socket()")

return 0

}

if (connect(sck, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) <0) {//如果使用该套接字连接到远程主机失败,报告错误,并返回

perror("error on connect()")

return 0

}write(sck, "DI\n\n", 4)//连接成功,发送内容为"DI\n\n"的消息,远程主机收到该消息,解析后生成目录列表,并将目录列表信息传递回来

printf("Remote directory listing:\n")//输出提示信息“远程主机正在生成目录列表”

while ((bytes = read(sck, databuf, FILEBUF_SIZE)) >0) { //从套接字的数据流中读取远程主机的返回信息(即目录列表),每次读取FILEBUF_SIZE个字节,直到全部读取完毕

write(fileno(stdout), databuf, bytes)//将每次读到的数据,输出到标准输出流(stdout),即屏幕上

bytesread += bytes//接收到的字节数累加

}

close(sck)/* Close the socket */ //通信完成,关闭套接字,关闭连接

return bytesread//返回读取到的字节数(即远程主机返回的信息的大小)

}


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/5923544.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-03-08
下一篇2023-03-08

发表评论

登录后才能评论

评论列表(0条)

    保存