c语言linux TCP长连接 socket收发范例 断开自动重连

原文链接:https://blog.csdn.net/chenhao0568/article/details/103420615

c语言linux TCP长连接 socket收发范例 断开自动重连
改进1:加入接收超时。可以做别的事,等有接收才响应

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <netinet/tcp.h>#include <string.h>#include <arpa/inet.h>#include <sys/socket.h>#include  <errno.h>#include    <sys/types.h>#include    <netdb.h>#include    <netinet/in.h>#include <time.h>#include <sys/timeb.h>#include <string.h>#include <stdio.h>#include <fcntl.h>#include <stdlib.h>#include <unistd.h>#include <sys/stat.h>#include <locale.h>// #include "extra/curl/curl.h"//#define IP "192.168.1.127"
#define IP "10.0.0.30"
#define PORT 3031
long time_last_connected = 0;// //参数解释
// //fd:       网络连接描述符
// //start:    首次心跳侦测包发送之间的空闲时间
// //interval: 两次心跳侦测包之间的间隔时间
// //count:    探测次数,即将几次探测失败判定为TCP断开
// int set_tcp_keepAlive(int fd, int start, int interval, int count) 
// {
//     int keepAlive = 1;
//     //入口参数检查 ,编程的好习惯。
//     if (fd < 0 || start < 0 || interval < 0 || count < 0)
//     return -1;   
//     //启用心跳机制,如果您想关闭,keepAlive置零即可
//     if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*) &keepAlive, sizeof(keepAlive)) == -1) 
//     {
//         perror("setsockopt");
//         return -1;
//     }
//     //启用心跳机制开始到首次心跳侦测包发送之间的空闲时间
//     if (setsockopt(fd, IPPROTO_TCP , TCP_KEEPIDLE, (void *) &start, sizeof(start)) == -1) 
//     {
//         perror("setsockopt");
//         return -1;
//     }
//     //两次心跳侦测包之间的间隔时间
//     if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, (void *) &interval, sizeof(interval)) == -1) 
//     {
//         perror("setsockopt");
//         return -1;
//     }
//     //探测次数,即将几次探测失败判定为TCP断开
//     if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, (void *) &count, sizeof(count)) == -1) 
//     {
//         perror("setsockopt");
//         return -1;
//     }
//     return 0;
// }
/***read_timeout - 读超时检测函数, 不包含读操作*@fd: 文件描述符*@waitSec: 等待超时秒数, 0表示不检测超时*成功(未超时)返回0, 失败返回-1, 超时返回-1 并且 errno = ETIMEDOUT**/
int read_timeout(int fd, long waitSec) 
{int returnValue = 0;if (waitSec > 0) {fd_set readSet;FD_ZERO(&readSet);FD_SET(fd, &readSet);    //添加struct timeval waitTime;waitTime.tv_sec = waitSec;waitTime.tv_usec = 0;       //将微秒设置为0(不进行设置),如果设置了,时间会更加精确do{returnValue = select(fd + 1, &readSet, NULL, NULL, &waitTime);}while (returnValue < 0 && errno == EINTR);   //等待被(信号)打断的情况, 重启selectif (returnValue == 0) {   //在waitTime时间段中一个事件也没到达,超时returnValue = -1;   //返回-1errno = ETIMEDOUT;}else if (returnValue == 1) {  //在waitTime时间段中有事件产生returnValue = 0; //返回0,表示成功}// 如果(returnValue == -1) 并且 (errno != EINTR), 则直接返回-1(returnValue)}printf("TCP read_timeout:%d\n",returnValue);return returnValue;
}
// /* activate_nonblock - 设置IO为非阻塞模式
//  * fd: 文件描述符
//  */
// void activate_nonblock(int fd)
// {
//     int ret;
//     int flags = fcntl(fd, F_GETFL);
//     if (flags == -1)
//     {
//         perror("fcntl error");
//     }
//     flags |= O_NONBLOCK;
//     ret = fcntl(fd, F_SETFL, flags);
//     if (ret == -1)
//     {
//         perror("fcntl error");
//     }
// }
// /* deactivate_nonblock - 设置IO为阻塞模式
//  * fd: 文件描述符
//  */
// void deactivate_nonblock(int fd)
// {
//     int ret;
//     int flags = fcntl(fd, F_GETFL);
//     if (flags == -1)
//     {
//         perror("fcntl error");
//     }
//     flags &= ~O_NONBLOCK;
//     ret = fcntl(fd, F_SETFL, flags);
//     if (ret == -1)
//     {
//         perror("fcntl error");
//     }
// }/* connect_timeout - 带超时的connect* fd: 套接字* addr: 输出参数,返回对方地址* wait_seconds: 等待超时秒数,如果为0表示正常模式* 成功(未超时)返回0,失败返回-1,超时返回-1并且errno = ETIMEDOUT*/
// int connect_timeout(int fd, struct sockaddr_in *addr, unsigned int wait_seconds)
// {
//     int ret;
//     socklen_t addrlen = sizeof(struct sockaddr_in);//     if (wait_seconds > 0)
//     {
//         activate_nonblock(fd);          //设置为非阻塞模式
//     }
//     printf("\n连接服务器开始\n");
//     ret = connect(fd, (struct sockaddr *) addr, addrlen);
//     printf("\n连接服务器开始[%d,%d]\n", ret,errno);
//     if (ret < 0 && errno == EINPROGRESS)
//     {
//         printf("connect EINPROGRESS\n");   //异步连接
//         fd_set connect_fdset;
//         struct timeval timeout;
//         FD_ZERO(&connect_fdset);
//         FD_SET(fd, &connect_fdset);//         timeout.tv_sec = wait_seconds;
//         timeout.tv_usec = 0;//         do
//         {
//         /* 一旦连接建立,套接字就可写 */
//             ret = select(fd + 1, NULL, &connect_fdset, NULL, &timeout);
//         }
//         while (ret < 0 && errno == EINTR);//         if (ret == 0)
//         {
//             errno = ETIMEDOUT;
//             return -1;
//         }
//         else if (ret < 0)
//         return -1;//         else if (ret == 1)
//         {
//       /* ret返回为1,可能有两种情况,一种是连接建立成功,一种是套接字产生错误
//        * 此时错误信息不会保存至errno变量中(select没出错),因此,需要调用
//        * getsockopt来获取 */
//             int err;
//             socklen_t socklen = sizeof(err);
//             int sockoptret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &socklen);
//             if (sockoptret == -1)
//             {
//                 return -1;
//             }
//             if (err == 0)
//             {
//                 ret = 0;
//             }
//             else
//             {
//                 errno = err;
//                 ret = -1;
//             }
//         }
//     }
//     if (wait_seconds > 0)
//     {
//         deactivate_nonblock(fd);
//     }
//     return ret;
// }
int tcp()
{printf("\n\n**********TCP开始连接%s:%d\n", IP, PORT);int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){printf("socket创建失败:%d\n", sockfd);close(sockfd);sleep(1);return -1;}// printf("socket创建成功:%d\n", sockfd);struct sockaddr_in ser;memset(&ser, 0, sizeof(ser));ser.sin_family = AF_INET;ser.sin_port = htons(PORT);ser.sin_addr.s_addr = inet_addr(IP);int res = connect(sockfd, (struct sockaddr *)&ser, sizeof(ser));if (res < 0){printf("socket连接失败:%d\n", res);close(sockfd);sleep(1);return -1;}printf("socket连接成功:%d\n", res);while (1){//发送//printf("please input:");fflush(stdin);//清理标准输入流,把多余的未被保存的数据丢掉。char buff[128] = "1234";//fgets(buff, 128, stdin);//buff[strlen(buff) - 1] = 0;if (strcmp(buff, "end") == 0) //end正常退出{close(sockfd);printf("end正常退出socket\n");return 0;}int sendret = send(sockfd, buff, strlen(buff), 0);if (sendret < 0){printf("socket发送失败:%d (0服务端断开,-1网络故障)\n", sendret);close(sockfd);return -1;}printf("socket发送成功:%d,内容:%s\n", sendret, buff);//接收char recvbuff[1024] = {0};printf("socket接收等待中\n");fflush(stdout);//清空输出缓冲区,并把缓冲区内容输出。int ret = read_timeout(sockfd, 10);if(ret==0){int recvret = recv(sockfd, recvbuff, 1023, 0);if (recvret <= 0){printf("socket接收失败:%d (0服务端断开,-1网络故障)\n", recvret);close(sockfd);return -1;}printf("socket接收成功:%d,内容:%s\n", recvret, recvbuff);}}
}
int main()
{while (1){tcp();}
}

阻塞

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define IP "192.168.1.127"
#define PORT 3031int tcp()
{printf("\n\n**********TCP开始连接%s:%d\n", IP, PORT);int sockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){printf("socket创建失败:%d\n", sockfd);close(sockfd);sleep(1);return -1;}// printf("socket创建成功:%d\n", sockfd);struct sockaddr_in ser;memset(&ser, 0, sizeof(ser));ser.sin_family = AF_INET;ser.sin_port = htons(PORT);ser.sin_addr.s_addr = inet_addr(IP);int res = connect(sockfd, (struct sockaddr *)&ser, sizeof(ser));if (res < 0){printf("socket连接失败:%d\n", res);close(sockfd);sleep(1);return -1;}printf("socket连接成功:%d\n", res);while (1){//发送//printf("please input:");fflush(stdout);char buff[128] = "1234";//fgets(buff, 128, stdin);//buff[strlen(buff) - 1] = 0;if (strcmp(buff, "end") == 0) //end正常退出{close(sockfd);printf("end正常退出socket\n");return 0;}int sendret = send(sockfd, buff, strlen(buff), 0);if (sendret < 0){printf("socket发送失败:%d (0服务端断开,-1网络故障)\n", sendret);close(sockfd);return -1;}printf("socket发送成功:%d,内容:%s\n", sendret, buff);//接收char recvbuff[128] = {0};printf("socket接收等待中\n");int recvret = recv(sockfd, recvbuff, 127, 0);if (recvret <= 0){printf("socket接收失败:%d (0服务端断开,-1网络故障)\n", recvret);close(sockfd);return -1;}printf("socket接收成功:%d,内容:%s\n", recvret, recvbuff);}
}
int main()
{while (1){tcp();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/402023.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Shell 脚本知识回顾 (六) —— Shell 函数

一、Shell函数&#xff1a;Shell函数返回值、删除函数、在终端调用函数 函数可以让我们将一个复杂功能划分成若干模块&#xff0c;让程序结构更加清晰&#xff0c;代码重复利用率更高。像其他编程语言一样&#xff0c;Shell 也支持函数。Shell 函数必须先定义后使用。 Shell 函…

ICE相关链接

ZeroC IceGrid介绍及demo构建&#xff08;使用IceBox&#xff09; ice grid 第一篇 ICE通信之IceGrid服务&#xff08;二&#xff09; IceGrid注册器复制 Ice服务详解及应用_IceGrid(01)IceGrid应用 配置手册 https://blog.csdn.net/abcdefg367/category_8275964.html ICE通信框…

C# 托管资源和非托管资源(Dispose、析构函数)

https://www.cnblogs.com/herenzhiming/articles/9691524.html 资源分类&#xff1a; 托管资源指的是.NET可以自动进行回收的资源&#xff0c;主要是指托管堆上分配的内存资源。托管资源的回收工作是不需要人工干预的&#xff0c;有.NET运行库在合适调用垃圾回收器进行回收。…

Shell 脚本知识回顾 (五) —— Shell 循环

一、Shell for循环 与其他编程语言类似&#xff0c;Shell支持for循环。 for循环一般格式为&#xff1a;for 变量 in 列表 docommand1command2...commandN done 列表是一组值&#xff08;数字、字符串等&#xff09;组成的序列&#xff0c;每个值通过空格分隔。每循环一次&…

android开发工具下载

android studio eclipse sdk adt

Shell 脚本知识回顾 (四) —— Shell 命令及Shell 相关语句

一、Shell echo命令 echo是Shell的一个内部指令&#xff0c;用于在屏幕上打印出指定的字符串。命令格式&#xff1a;echo arg您可以使用echo实现更复杂的输出格式控制。 显示转义字符 echo "\"It is a test\""结果将是&#xff1a;"It is a test"…

qt工程。。。。。。

分享Qt多工程多目录的编译案例&#xff0c;subdirs Qt编译debug和release版本–CONFIG(debug,debug|release) QT工程pro设置实践(with QtCreator)----非弄的像VS同样才顺手? Qt创建动态库并添加动态库版本号 qmake&#xff1a;变量手册 QtCreator按顺序编译多个子项目

Shell 脚本知识回顾 (三) —— 替换、运算符、字符串、数组

一、Shell替换&#xff1a;Shell变量替换&#xff0c;命令替换&#xff0c;转义字符 如果表达式中包含特殊字符&#xff0c;Shell 将会进行替换。例如&#xff0c;在双引号中使用变量就是一种替换&#xff0c;转义字符也是一种替换。 举个例子&#xff1a; [cpp] view plaincop…

最幸福的事就是吃饺子

中午了&#xff0c;不知道吃什么&#xff0c;就去煮了点饺子&#xff0c;人呼呼的&#xff0c;吃完了很暖和~~下午出去&#xff0c;晚上回来&#xff0c;一天就这样过了~~转载于:https://blog.51cto.com/tina1314luky/1343466

Shell 脚本知识回顾 (二) —— Shell变量

一、Shell变量&#xff1a;Shell变量的定义、删除变量、只读变量、变量类型 Shell支持自定义变量。定义变量 定义变量时&#xff0c;变量名不加美元符号&#xff08;$&#xff09;&#xff0c;如&#xff1a; [cpp] view plaincopy variableName"value" 注意&…

Shell 脚本知识回顾 (一) —— 基础篇

一、Shell简介&#xff1a;什么是Shell&#xff0c;Shell命令的两种执行方式 Shell本身是一个用C语言编写的程序&#xff0c;它是用户使用Unix/Linux的桥梁&#xff0c;用户的大部分工作都是通过Shell完成的。Shell既是一种命令语言&#xff0c;又是一种程序设计语言。作为命令…

c实现面向对象编程(3)

http://blog.csdn.net/kennyrose/article/details/7564105

C 与 JAVA 的对比分析

Sun 公司推出的Java 是面向对象程序设计语言&#xff0c;其适用于Internet 应用的开发&#xff0c;称为网络时代重要的语言之一。Java 可以用认为是C 的衍生语言&#xff0c;与C 在大量元以内成分保持相同&#xff0c;例如此法结构、表达式语句、运算符等与C基本一致&#xff1…

红帽集群RHCS

1、简介&#xff1a;RHCS是RedHatClusterSuite的缩写&#xff0c;也就是红帽子集群套件&#xff0c;RHCS是一个能够提供高可用性、高可靠性、负载均衡、存储共享且经济廉价的集群工具集合&#xff0c;它将集群系统中三大集群架构融合一体&#xff0c;可以给web应用、数据库应用…

Java 基础——类的加载

当程序主动使用某个类时&#xff0c;如果该类还未被加载到内存中&#xff0c;系统会通过加载&#xff0c;连接&#xff0c;初始化三个步骤来对该类进行初始化&#xff0c;JVM将会连续完成这三个步骤&#xff0c;也把这三个步骤统称为类加载或类初始化&#xff1b; 类加载指的是…

HDUOJ-----1556Color the ball

Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6787 Accepted Submission(s): 3549 Problem DescriptionN 个气球排成一排&#xff0c;从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <…

Java 基础——数组解析

数组对于每一门编辑应语言来说都是重要的数据结构之一&#xff0c;当然不同语言对数组的实现及处理也不尽相同。 Java语言中提供的数组是用来存储固定大小的同类型元素。 可以声明一个数组变量&#xff0c;如numbers[100]来代替直接声明100个独立变量number0&#xff0c;number…

《在你身边,为你设计》-哪位知道下载、在线阅读地址啊?

《在你身边&#xff0c;为你设计》-前端UI必读出自腾讯CDChttp://cdc.tencent.com/?p6761今天听同事说这本书写的非常好&#xff0c;改变了他关于前端UI的许多看法&#xff0c;可谓&#xff1a;醍醐灌顶。可惜我网上找了下都需要Money买&#xff0c;哪位有在线阅读、PDF下载地…

Java 基础——类和对象

Java作为一种面向对象语言。支持以下基本概念&#xff1a; •多态 •继承 •封装 •抽象 •类 •对象 •实例 •方法 •消息解析 本节我们重点研究类与对象的概念。 对象&#xff1a;对象是类的一个实例&#xff0c;有状态和行为。例如&#xff0c;一条狗是一个对象&#xff0c…

报告显示Q2 Android平板电脑全球市场份额达67%

网易科技讯 7月30日消息&#xff0c;据国外媒体报道&#xff0c;市场调研公司Strategy Analytics最新公布的报告显示&#xff0c;2013年第二季度平板电脑全球出货量达到5170万台&#xff0c;比去年同期的3610万台增长43&#xff05;&#xff0c;其中Android、iOS和Windows平板电…