winsock时间循环发送消息不起作用

winsock time loop send message does not work

使用 winsock,我有一个客户端和一个服务器,当 connect 完成后,我第一次发送一条消息,我可以在服务器中接收它,但在那之后,当我做一个时间循环时,我可以不要在屏幕上显示它们。时间循环内的发送消息不会 return 出错。我知道这是一个奇怪的问题,但如果你看一下发送函数所在的 timerCb,它不会 return 错误,但在我的服务器中我无法打印它。我也尝试用 recv 参数创建一个新的 while 循环,但它仍然不起作用。

这是我的客户,

char receivingMessage[1000];
char messageInitiation[90] = "Hello YUMATKARA, conn pls bro hhhasf7sasflljh89";
VOID CALLBACK timerCb(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
//main
  SetTimer(NULL, 0, 3600, timerCb);

  if(WSAStartup(MAKEWORD(2, 2), &ws) != 0){
    printf("WSA err %d \n", GetLastError());
  }else{
  }

  if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET){
    printf("Invalid Socket \n");
  }else{
    printf("socket binded \n");
  }

  rmtServer.sin_addr.s_addr = inet_addr("127.0.0.1");
  rmtServer.sin_port = htons(4743);
  rmtServer.sin_family = AF_INET;

  if((connect(s, (struct sockaddr*)&rmtServer, sizeof(struct sockaddr_in))) != 0){
    printf("\n err %d", GetLastError());
  }else{
    printf("\n connected");
    send(s, messageInitiation, strlen(messageInitiation), 0);
    recv(s, receivingMessage, 1000, 0);
    printf("\n %s", receivingMessage);
    int liop;
    liop = strcmp(receivingMessage, "I got you!!");
    if(liop == 0){
      connectedYet = TRUE;
    }
    printf("\n is it true: ? %d\n", connectedYet);
  }

  while(GetMessage(&message, NULL, 0, 0) > 0){
    TranslateMessage(&message);
    DispatchMessage(&message);
  }

//outside main

VOID CALLBACK timerCb(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime){
  char *msgg = "Hello YUMATKARA, conn pls bro hhhasf7sasflljh89";
  printf("\n%s\n", "timing");
  if(send(s, msgg, strlen(msgg), 0) == SOCKET_ERROR){
    printf("err :%d\n", GetLastError());
  }
}

这是我的服务器

#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdParam, int iCmdShow) {
  MSG message;
  WSADATA ws;
  SOCKET s, incomingSocket;
  struct sockaddr_in server, client;
  char incomingMessage[1800];
  int recvState;
  WSAStartup(MAKEWORD(2, 2), &ws);

  s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  server.sin_port = htons(4743);
  server.sin_addr.s_addr = inet_addr("127.0.0.1");
  server.sin_family = AF_INET;

  bind(s, (struct sockaddr *)&server, sizeof(server));

  listen(s, 1300);

  int g = sizeof(struct sockaddr_in);

  while((incomingSocket = accept(s, (struct sockaddr *)&client, &g)) != INVALID_SOCKET){
      printf("%s\n", inet_ntoa(client.sin_addr));
      printf("conn\n");
      if((recvState = recv(incomingSocket, incomingMessage, 2500, 0)) == SOCKET_ERROR){
      }else{
        int as;
        if((as = strcmp(incomingMessage, "Hello YUMATKARA, conn pls bro hhhasf7sasflljh89")) == 0){
          printf("\n identical");
          send(incomingSocket, "I got you!!", 11, 0);
        }
        printf("\n :%s\n", incomingMessage);
      }
  }

  if(incomingSocket == INVALID_SOCKET){
    printf("invalid socket");
  }

  return 0;
}

更新

我已经在我的服务器代码中添加了这个,在 return 0 它根本不显示任何东西之前。

  while((recvState = recv(incomingSocket, incomingMessage, 50, 0)) > 0) {
    printf("\n new msg %s\n", incomingMessage);
  }

TCP 是字节流,不像您期望的那样是面向消息的。

recv() 不保证 return 完整的消息。它可以 return 少至 1 个字节,也可以 return 消息中的部分字节,甚至是多条消息中的字节。您必须在代码逻辑中处理缓冲和消息框架。并注意它的 return 值,这样你就知道它实际读取了多少。如果您期望的数据多于读取的数据,则必须再次调用 recv() 以读取其余部分,可能需要多次。所以使用循环。

所以,要么:

  1. 让发件人在发送实际字符之前将字符串的长度作为固定长度值发送。然后让接收方读取长度,知道要读取多少个字符。

  2. 让发送方在每个字符串后发送一个唯一的终止符,比如空字符甚至 CRLF,然后接收方可以继续读取直到遇到终止符。

至于send(),也不保证发送完整的数据。它可以发送少至 1 个字节,或者至少少于您请求的字节数。所以你也必须注意它的 return 值,才能知道它实际发送了多少。如果它不能一次发送所有内容,则您必须再次调用它以发送任何剩余数据,可能需要多次。所以使用循环。

例如,尝试更像这样的东西:

客户:

const char messageInitiation* = "Hello YUMATKARA, conn pls bro hhhasf7sasflljh89";

char* readStr(SOCKET s)
{
    char *str = NULL;
    char buffer[100], ch;
    int buf_len = 0, str_len = 0, ret;

    do
    {
        ret = recv(s, &ch, 1, 0);
        if (ret == SOCKET_ERROR)
        {
            printf("recv err %d\n", WSAGetLastError());
            return SOCKET_ERROR;
        }

        if (ch == '[=10=]')
            break;

        if (buf_len == sizeof(buffer))
        {
            char *newstr = (char*) realloc(str, str_len + buf_len + 1);
            if (!newstr)
            {
                printf("memory err\n");
                free(str);
                return NULL;
            }

            str = newstr;

            memcpy(str + str_len, buffer, buf_len);
            str_len += buf_len;

            buf_len = 0;
        }

        buffer[buf_len++] = ch;
    }
    while (true);

    if (buf_len > 0)
    {
        char *newstr = (char*) realloc(str, str_len + buf_len + 1);
        if (!newstr)
        {
            printf("memory err\n");
            free(str);
            return NULL;
        }

        str = newstr;

        memcpy(str, buffer, buf_len);
        str_len += buf_len;
    }

    str[str_len] = '[=10=]';

    return str;
}

int sendStr(SOCKET s, const char *str)
{
    const unsigned char *pstr = (const unsigned char*) str;
    int len = strlen(str) + 1, ret;

    do
    {
        ret = send(s, pstr, len, 0);
        if (ret == SOCKET_ERROR)
        {
            printf("send err %d\n", WSAGetLastError());
            return SOCKET_ERROR;
        }
        pstr += ret;
        len -= ret;
    }
    while (len > 0);

    return 0;
}

/* alternatively:

int readAll(SOCKET s, void *data, int len)
{
    unsigned char *pdata = (unsigned char *) data;
    int ret;

    while (len > 0)
    {
        ret = recv(s, pdata, len, 0);
        if (ret == SOCKET_ERROR)
        {
            printf("recv err %d\n", WSAGetLastError());
            return SOCKET_ERROR;
        }
        pdata += ret;
        len -= ret;
    }

    return 0;
}

int readStr(SOCKET s)
{
    int32_t len = 0;
    if (readAll(s, &len, sizeof(len)) == SOCKET_ERROR)
        return NULL;

    char *str = (char*) malloc(len + 1);
    if (!str)
    {
        printf("memory err\n");
        return NULL;
    }

    if (readAll(s, str, len) == SOCKET_ERROR)
    {
        free(str);
        return NULL;
    }

    str[len] = '[=10=]';

    return str;
}

int sendAll(SOCKET s, const void *data, int len)
{
    const unsigned char *pdata = (const unsigned char*) data;
    int ret;

    while (len > 0)
    {
        ret = send(s, pdata, len, 0);
        if (ret == SOCKET_ERROR)
        {
            printf("send err %d\n", WSAGetLastError());
            return SOCKET_ERROR;
        }
        pdata += ret;
        len -= ret;
    }

    return 0;
}

int sendStr(SOCKET s, const char *str)
{
    int32_t len = strlen(str) + 1;
    int ret = sendAll(s, &len, sizeof(len));
    if (ret == 0)
        ret = sendAll(s, str, len);
    return ret;
}
*/

VOID CALLBACK timerCb(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
    printf("\n%s\n", "timing");
    if (!sendStr(s, messageInitiation))
        PostQuitMessage(0);
}

int main()
{
    WSADATA ws;
    int ret = WSAStartup(MAKEWORD(2, 2), &ws);
    if (ret != 0)
    {
        printf("WSA err %d\n", ret);
        return -1;
    }

    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (s == INVALID_SOCKET)
    {
        printf("socket err %d\n", WSAGetLastError());
        WSACleanup();
        return -1;
    }

    printf("socket created\n");

    struct sockaddr_in rmtServer = {};
    rmtServer.sin_family = AF_INET;
    rmtServer.sin_addr.s_addr = inet_addr("127.0.0.1");
    rmtServer.sin_port = htons(4743);

    if (connect(s, (struct sockaddr*)&rmtServer, sizeof(struct sockaddr_in)) == SOCKET_ERROR)
    {
        printf("connect err %d\n", WSAGetLastError());
        closesocket(s);
        WSACleanup();
        return -1;
    }

    printf("connected\n");

    if (sendStr(s, messageInitiation) != 0)
    {
        closesocket(s);
        WSACleanup();
        return -1;
    }

    char *receivingMessage = recvStr(s);
    if (!receivingMessage)
    {
        closesocket(s);
        WSACleanup();
        return -1;
    }

    printf("%s\n", receivingMessage);
    BOOL connectedYet = (strcmp(receivingMessage, "I got you!!") == 0);
    printf("is it true: ? %d\n", connectedYet);
    free(receivingMessage);

    SetTimer(NULL, 0, 3600, timerCb);

    MSG message;
    while (GetMessage(&message, NULL, 0, 0) > 0)
    {
        TranslateMessage(&message);
        DispatchMessage(&message);
    }

    closesocket(s);
    WSACleanup();

    return 0;
}

服务器:

#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// see client code above
char* readStr(SOCKET s);
int sendStr(SOCKET s, const char *str);

int main()
{
    struct sockaddr_in server = {0}, client;

    WSADATA ws;
    int ret = WSAStartup(MAKEWORD(2, 2), &ws);
    if (ret != 0)
    {
        printf("WSA err %d\n", ret);
        return -1;
    }

    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (s == INVALID_SOCKET)
    {
        printf("socket err %d\n", WSAGetLasatError());
        WSACleanup();
        return -1;
    }

    struct sockaddr_in server = {};
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr("127.0.0.1");
    server.sin_port = htons(4743);

    ret = bind(s, (struct sockaddr *)&server, sizeof(server));
    if (ret == SOCKET_ERROR)
    {
        printf("bind err %d\n", WSAGetLastError());
        closesocket(s);
        WSACleanup();
        return -1;
    }

    if (listen(s, 10) == SOCKET_ERROR)
    {
        printf("listen err %d\n", WSAGetLastError());
        closesocket(s);
        WSACleanup();
        return -1;
    }

    int g, iResult;
    struct sockaddr_in client;

    do
    {
        g = sizeof(client);

        SOCKET incomingSocket = accept(s, (struct sockaddr *)&client, &g);
        if (incomingSocket == INVALID_SOCKET)
        {
            printf("accept err %d\n", WSAGetLastError());
            closesocket(s);
            WSACleanup();
            return -1;
        }

        printf("%s conn\n", inet_ntoa(client.sin_addr));

        char *incomingMessage = recvStr(incomingSocket);
        if (incomingMessage)
        {
            printf("%s\n", incomingMessage);
            if (incomingMessage, "Hello YUMATKARA, conn pls bro hhhasf7sasflljh89") == 0)
            {
                printf("identical\n");
                sendStr(incomingSocket, "I got you!!");
            }
        }

        closesocket(incomingSocket);
    }
    while (true);

    return 0;
}