c - 使用winsock 2 lib在Windows中重新启动断开的TCP连接

标签 c windows sockets tcp winsock

我正在开发一个c程序,该程序应该记录来自norma 5000的数据,但它看起来像norma tcpconnection在任意时间(0.2-6小时)后随机关闭,但我需要记录比这更长的时间。

当它关闭连接时,我可以重新启动程序,它将继续记录。所以我想到了当 tcpconnection 中断时重新启动我的套接字。但我每次重新启动都不起作用..我认为你想看的功能是 shutdownCon、init 和 main。

我的问题是:我做错了什么?

当 tcp 连接停止工作时出现 winsock 错误 10053 (WSAECONNABORTED) 或 10054 (WSAECONNRESET)。

https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx

#pragma comment(lib, "Ws2_32.lib")
#define WIN 1
#define debug 1

#include <winsock2.h>
#include <windows.h>

#include <stdio.h>

#include <sys/timeb.h>
#include <time.h>

#define HOST "192.168.0.101"
#define PORT 23

#define SOCKET_HANDLE_FMT_PFX ""
#define SOCKET_HANDLE_FMT "u" /* "%u" - 'typedef u_int SOCKET' */
typedef SOCKET socket_handle_t;

typedef struct {
    socket_handle_t h;
} *socket_t;
/****************************************************************************
**/
static void Delay(double seconds)
{
    Sleep((DWORD)(seconds * 1000));
}
/****************************************************************************
**/
void wsa_error(char *func,int error)
{
    fprintf(stderr,"%s() failed, error %d\n",
    func,error == -1 ? WSAGetLastError() : error);

    int c;  /* must be int to hold EOF */ 
    while((c = getchar()) != '\n' && c != EOF); 
}
/****************************************************************************
**/
int socket_setup(void)
{
    #if WIN
    WSADATA wsaData;
    int wsaerrno;
    /*
    * Initialize Windows Socket DLL
    */
    if ( (wsaerrno = WSAStartup(
    MAKEWORD(1,1), /* at least version 1.1 */
    &wsaData)) != 0 )
    {
        wsa_error("WSAStartup",wsaerrno);
        return -1;
    }
    #endif /* WIN */
    return 0; /* OK */
}
/****************************************************************************
**/
int socket_cleanup(void)
{
    #if WIN
    if ( WSACleanup() == SOCKET_ERROR )
        wsa_error("WSACleanup",-1);
    #endif
    return 0; /* OK */
}
/****************************************************************************
**/
socket_t socket_create(void)
{
    socket_handle_t sh;
    socket_t s;
    sh = socket(AF_INET,SOCK_STREAM,0);
    #if WIN
    if ( sh == INVALID_SOCKET )
    {
        wsa_error("socket",-1);
        return NULL;
    }
    #endif
    s = calloc(1,sizeof(*s));
    if ( !s )
        return NULL;
    s->h = sh;
    return s; /* OK */
}
/****************************************************************************
**/
int socket_connect(socket_t s,struct sockaddr *addr,int addrlen)
{
    int ret = 0; /* OK */
    #if WIN
    if ( connect(s->h,addr,addrlen) == SOCKET_ERROR )
    {
        wsa_error("connect",-1);
        return -1;
    }
    #endif
    return 0; /* OK */
}
/****************************************************************************
**/
int socket_recv(socket_t s,void *buf,int len,int flags)
{
    register int l;
    #if WIN
    l = recv(s->h,buf,len,flags);
    if ( l == SOCKET_ERROR )
    {
        wsa_error("recv",-1);
        return -1;
    }
    #endif
    return l;
}
/****************************************************************************
**/
int socket_send(socket_t s,void *buf,int len,int flags)
{
    register int slen; /* sent length */
    #if WIN
    slen = send(s->h,buf,len,flags);
    if ( slen == SOCKET_ERROR )
    {
        wsa_error("send",-1);
        return -1;
    }
    #endif
    return slen;
}
/****************************************************************************
**/
int socket_puts(socket_t s,char *str)
{
    char buf[1024];
    strcpy(buf,str);
    strcat(buf,"\n");
    if ( socket_send(s,buf,strlen(buf),0) < 0 )
        return -1;
    return 0;
}
/****************************************************************************
**/
int socket_gets(socket_t s,char *str)
{
    char buf[1024];
    char *p;
    if ( socket_recv(s,buf,sizeof(buf),0) < 0 )
    return -1;
    if ( (p = memchr(buf,'\n',sizeof(buf))) != NULL )
    {
        if ( p > buf && p[-1] == '\r' )
            p--;
        *p = '\0';
    }
    else
        buf[sizeof(buf)-1] = '\0';
    strcpy(str,buf);
    return strlen(str);
}
/****************************************************************************
**/
/*is some thing wrong here?*/
int shutdownCon(socket_t s){
    char buff[1024];
    if (shutdown(s->h,2)== SOCKET_ERROR)
    {
        wsa_error("shutdownCon",-1);
        return -1;
    }

    while(socket_gets(s,buff)> 1);
    if(closesocket(s->h) == SOCKET_ERROR)
    {
        wsa_error("shutdownCon",-1);
        return -1;
    }
    socket_cleanup();
    return 0;
}
/*is some thing wrong here?*/
int init(socket_t *s){
    struct sockaddr_in saddr;
    struct sockaddr_in *addr_in = (struct sockaddr_in *)&saddr;
    /* socket (TCP/IP) API initialization: */
    if ( socket_setup() < 0 )
    return -1;
    /*
    * Connect to the instrument:
    */
    /* set destination IP address and TCP port: */
    memset(addr_in,0,sizeof(struct sockaddr_in));
    addr_in->sin_family = AF_INET;
    addr_in->sin_port = htons(PORT);
    addr_in->sin_addr.s_addr = inet_addr(HOST);
    /* create socket: */
    *s = socket_create();
    if ( !*s )
        return -1;
    #if debug
    fprintf(stderr,"socket_connect() ...\n");
    #endif
    if ( socket_connect(*s,(struct sockaddr *)&saddr,sizeof(saddr)) < 0 )
        return 1;
    #if debug
    fprintf(stderr,"socket_connect(): done\n");
    #endif
    return 1;
}
int recon(socket_t *s){
    shutdownCon(*s);
    init(s);
    return 0;
}

void printTime(){
   struct _timeb timebuffer;
   char *timeline;

   _ftime( &timebuffer );
   timeline = ctime( & ( timebuffer.time ) );

   printf( "The time is %.19s.%hu %s", timeline, timebuffer.millitm, &timeline[20] );
}
int main(int argc,char *argv[])
{
    socket_t s;

    char buffer[1024];
    char oper[1024];

    init(&s);

    #if debug
    fprintf(stderr,"trying to get id from norma \n");
    if ( socket_puts(s,"*IDN?") < 0 )
        return 1;
    if ( socket_gets(s,buffer) < 0 )
        return 1;
    puts(buffer);
    #endif
    //##################CONF FROM FLUKE#####################
    /* Bring the instrument into a default state: */
    //socket_puts(s,"*RST");
    /* Select three wattmeter configuration: */
    //socket_puts(s,"ROUT:SYST \"3W\"");
    /* SYNC source = voltage phase 1: */
    //socket_puts(s,"SYNC:SOUR VOLT1");
    /* Set voltage range on voltage channel 1 to 300 V: */
    //socket_puts(s,"VOLT1:RANG 300.0");
    /* Set current channel 1 to autorange: */
    //socket_puts(s,"CURR1:RANG:AUTO ON");
    /* Set averaging time to 1 second: */
    //socket_puts(s,"APER 1.0");
    /* Select U, I, P measurement: */
    //socket_puts(s,"FUNC \"VOLT1\",\"CURR1\",\"POW1:ACT\"");
    /* Run continuous measurements: */
    //socket_puts(s,"INIT:CONT ON");
    //######################################################
    socket_puts(s,"SYST:KLOC REM");
    socket_puts(s,"*RST");
    socket_puts(s,"ROUT:SYST \"3w\"");
    socket_puts(s,"APER 0.025");
    socket_puts(s,"INP1:COUP DC");
    socket_puts(s,"FUNC \"VOLT1\",\"CURR1\",\"POW1\",\"POW1:APP\",\"POW1:ACT\",\"PHASE1\"");
    socket_puts(s,"INIT:CONT ON");

    Delay(5.0); /* Wait 2 seconds */
    int opstat = -1;

    while(1){
        //if(opstat != -1)
        //  recon(&s);

        opstat = 0;
        while((opstat & 0x400) == 0){
            if(socket_puts(s,"STAT:OPER:EVEN?")==-1){
                recon(&s);
                continue;
            }
            memset(oper,0,sizeof(oper));
            if(socket_gets(s,oper) == -1){
                recon(&s);
                continue;
            }
            opstat = atoi(oper);
        }

        if(socket_puts(s,"DATA?") == -1){/* Query the measurement */
                recon(&s);
                continue;
        } 
        memset(buffer,0,sizeof(buffer)); /* Clear buffer */
        if(socket_gets(s,buffer) == -1){/* read values */
                recon(&s);
                continue;
        }

        puts(buffer); /* Print the value on the screen */
        //Delay(1.0); /* Wait 2 seconds */
        printTime();
    }

    return 0;
}
/****************************************************************************
**/

最诚挚的问候,宝特

最佳答案

当对 WinSock2 函数的调用之一失败时,“shutdownCon”函数不应提前返回。例如,如果调用“shutdown”失败,“shutdownCon”会报告错误,然后退出,而不调用“closesocket”或“socket_cleanup”。因此,当“shutdownCon”失败时,它会使套接字和 WinSock2 库处于不同的状态(使您的程序难以可靠地继续,因为它不知道其中任何一个的状态)。

如果我是你,我也会将WinSock2库的初始化和套接字的初始化分开。我会在程序开始时初始化一次 WinSock2 库,并且永远不会清理它。换句话说,将从“init”中取出对“socket_setup”的调用并将其放入“main”中(当然在对“init”的调用之前),并将对“socket_cleanup”的调用从“shutdownCon”中取出。

如果上述方法都没有帮助,您可以尝试在关闭套接字和初始化新套接字之间插入一个延迟。如果这对您的程序没有帮助,您的程序可能需要开始检查 WinSock2 库返回的错误值,并根据错误的内容执行不同的操作。

关于c - 使用winsock 2 lib在Windows中重新启动断开的TCP连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31205776/

相关文章:

.net - .NET 中的 RIO(注册 I/O)套接字

c - socket 清洁

C - 1/n 数之和

c - 如何在c中初始化未知大小的数组

c - 为什么 printf() 不将此整数输出为 float ?

c++ - 在 C++ 中检测 youtube 的全屏模式

c - 服务器没有在预期的位置监听

c - 为什么这个程序在输入的中间意外停止

c - 二叉树的中序后继

windows - NPM 已停止在 Windows 7 64 位上工作,在安装/更新时挂起