linux网络编程之常连接

    linux嵌入式开发中,网络编程是绕不开的,现在设备的IP地址一般都是通过dhcp自动获取的,没有一个固定不变的IP,在和服务器进行通信时就不能才用既是客户端又是服务器的写法。而应采用常连接的方式,即服务器不需特意知道客户端的ip,只需知道一个TCP/IP的连接即可。本文来讲解一下嵌入式设备中的客户端网络编程。


一 、网络编程中的常用函数介绍


经常使用的函数主要有:

(1)getsockopt,用于获取网络套接字选项。

(2)setsockopt,用于设置网络套接字选项。

(3)connect,连接服务器。


二 、 检测网络连接状况


int SocketConnected(int sock) 
{ 
    if(sock <= 0) 
        return 0; 
    struct tcp_info info; 
    int len = sizeof(info); 
    getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len); 
    if((info.tcpi_state == TCP_ESTABLISHED)) 
    { 
        printf("socket connected\n"); 
        return 1; 
    } 
    else 
    { 
        printf("socket disconnected\n"); 
        return 0; 
    } 
}

三 、 常连接服务器

int Connect_to_Remote_Tcp_Server(void)
{
    struct sockaddr_in sk_address;
    int sockaddr_len;
    int remote_tcp_client_fd =0;
    int remote_tcp_client_res=0;
	
    int nNetTimeout=1000;//2秒 
    int keepAlive = 1; // 开启keepalive属性
    int keepIdle = 60; 
    int keepInterval = 60; 
    int keepCount = 3; 

	long lip;
	memcpy(&lip,devpara.sysdevip.serverip,4);
	memset(&sk_address,0,sizeof(sk_address));
	sk_address.sin_family = AF_INET;
	sk_address.sin_addr.s_addr = lip;
	sk_address.sin_port = htons(CMDTCPSERVEPORT);
	sockaddr_len = sizeof(sk_address);

    remote_tcp_client_fd = socket(AF_INET, SOCK_STREAM, 0); 
    if (remote_tcp_client_fd == -1)
    {
         perror ("socket call failed");
         exit (errno);
   
   }                                                        
   net_socket_setblock(remote_tcp_client_fd, 0);

    remote_tcp_client_res = connect(remote_tcp_client_fd, (struct sockaddr *)&sk_address,sockaddr_len);
    if(remote_tcp_client_res!=0)  
  	{  
       if(errno != EINPROGRESS) {
					printf("socket connected failed\n");
					close(remote_tcp_client_fd);
					return -1;
				} 
				fd_set set;
				FD_ZERO(&set);
				FD_SET(remote_tcp_client_fd, &set);
        struct timeval connect_tmout;
				connect_tmout.tv_sec=1;
				connect_tmout.tv_usec=0;
				if( select(remote_tcp_client_fd+1, NULL, &set, NULL, &connect_tmout) <= 0){
					printf("socket connected timeout\n");
					close(remote_tcp_client_fd);
					return -1;
				}
    }
	net_socket_setblock(remote_tcp_client_fd, 1);      
    setsockopt(remote_tcp_client_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));
    setsockopt(remote_tcp_client_fd, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));
    setsockopt(remote_tcp_client_fd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
    setsockopt(remote_tcp_client_fd, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));
    //发送时限
    setsockopt(remote_tcp_client_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&nNetTimeout,sizeof(int));
    //接收时限
    setsockopt(remote_tcp_client_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout,sizeof(int));
    return remote_tcp_client_fd;
}

设置阻塞方式或是非阻塞方式

void net_socket_setblock(int s, int is_block)
{
	int opts=fcntl(s, F_GETFL);
	if(opts < 0) return;

	if(is_block)
		opts = opts & ~O_NONBLOCK;
	else
		opts = opts | O_NONBLOCK;
	fcntl(s, F_SETFL, opts);
}

四 、 实例

void main()
{
    int fd;
    pthread_t	skrec_thread;
    if(SocketConnected(fd) == 0)     
    {
 	    fd = Connect_to_Remote_Tcp_Server();
 	    if(fd >= 0)
 	    { 
 	        pthread_create(&skrec_thread,NULL,Socket_Data_Proc,fd);
		    pthread_detach(skrec_thread);    
 	   }	 
    }		
}

其中Socket_Data_Proc为数据接收函数。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值