当前位置: 首页 > 知识库问答 >
问题:

send()时套接字失去连接

韦睿
2023-03-14

我想用C语言为我的世界建立一个假的播放器。

我的Minecraft服务器(bukkit)正在本地IP 192.168.1.141上的端口25565上侦听

当我启动应用程序时(当它通过套接字发送数据时),bukkit服务器会说:“192.168.1.141:XXXXX失去连接”,并且

socked created
socked connected
to send data = (smilie)kekos91;192.168.1.141:25565
to send length = 27
send !
response data = (a strange symbol)
response length = 1
socket disconnected
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winsock2.h>

int main()
{
    char pseudo[] = "kekos91;192.168.1.141:25565";
    int pseudoLen = strlen(pseudo);
    
    char *packet = NULL;
    packet = (char*)malloc(3 + ((pseudoLen)*sizeof(char)*2));
    if(packet == NULL)
    {
        return -1;
    }
    memset(packet, '\0', sizeof(packet));
    packet[0] = (char)0x02;
    strcat(packet, pseudo);
    int pLenght = strlen(packet);
    
    char handshake[200];
    
    HANDLE hConsole;
    WSADATA wsaData;
    int iResult = 0;

    SOCKET serverSocket;
    sockaddr_in serverInfos;

    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        printf("WSAStartup() failed with error: %d\n", iResult);
        return -1;
    }

    serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (serverSocket == INVALID_SOCKET) {
        printf("socket function failed with error: %i\n", WSAGetLastError());
        WSACleanup();
        return -1;
    }
    printf("socket created\n");

    serverInfos.sin_family = AF_INET;
    serverInfos.sin_addr.s_addr = inet_addr("192.168.1.141");
    serverInfos.sin_port = htons(25565);

    iResult = connect(serverSocket, (SOCKADDR *)&serverInfos, sizeof(serverInfos));
    if (iResult == SOCKET_ERROR)
    {
        printf("connect function failed with error: %i\n", WSAGetLastError());
        iResult = closesocket(serverSocket);
        if (iResult == SOCKET_ERROR)
        {
           printf("closesocket function failed with error: %i\n", WSAGetLastError());
        }
        WSACleanup();
        return -1;
    }
    printf("socket connected\n");
    
    
    
    printf("to send data = %s\n", packet);
    printf("to send length = %i\n", pseudoLen);
    Sleep(500); // after this point, the connection is loose :(
    if(send(serverSocket, (char*)packet , pLenght, 0) == SOCKET_ERROR)
    {
        printf("send function failed with error: %i\n", WSAGetLastError());
        iResult = closesocket(serverSocket);
        if (iResult == SOCKET_ERROR)
        {
           printf("closesocket function failed with error: %i\n", WSAGetLastError());
        }
        WSACleanup();
        return -1;
    }
    free(packet);
    
    printf("send !\n");
    
    
    
    
    if(recv(serverSocket, (char*)&handshake, 200, 0) == SOCKET_ERROR)
    {
        printf("recv function failed with error: %i\n", WSAGetLastError());
        iResult = closesocket(serverSocket);
        if (iResult == SOCKET_ERROR)
        {
           printf("closesocket function failed with error: %i\n", WSAGetLastError());
        }
        WSACleanup();
        return -1;
    }
    
    printf("response data = %s\n", handshake);      
    printf("response length = %i\n", strlen(handshake)); 
     
    iResult = closesocket(serverSocket);
    if (iResult == SOCKET_ERROR) {
        printf("closesocket function failed with error %i\n", WSAGetLastError());
        WSACleanup();
        return -1;
    }
    printf("socket disconnected.\n");
    
    WSACleanup();
    Sleep(5000);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winsock2.h>

int main()
{
    int iSocketResult = 0; // it will retrieve sockets return functions, like send / recv / errors
    
    wchar_t wcPseudo[] = L"kekos91;192.168.1.141:25565";
    int iPseudoLen = wcslen(wcPseudo);
    
    char *pPacket = NULL;
    pPacket = (char*)malloc(3 + ((iPseudoLen)*sizeof(char)*2));
    if(pPacket == NULL)
    {
        return -1;
    }
    pPacket[0] = 0x02;
    
    
    *(short*)( pPacket + 1 ) = htons( iPseudoLen );
    memcpy( pPacket + 3, wcPseudo, iPseudoLen * sizeof( wchar_t ));

    int iPacketLen = 3 + iPseudoLen*sizeof(wchar_t) ;    

    char *handshake  = NULL;
    handshake = (char*)malloc(sizeof(char)*200);
    if(handshake == NULL)
    {
        return -1;
    }
    
    
    HANDLE hConsole;
    WSADATA wsaData;        
    
    SOCKET serverSocket;
    sockaddr_in serverInfos;

    iSocketResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iSocketResult != NO_ERROR) {
        printf("WSAStartup() failed with error: %d\n", iSocketResult);
        return -1;
    }

    serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (serverSocket == INVALID_SOCKET) {
        printf("socket function failed with error: %i\n", WSAGetLastError());
        WSACleanup();
        return -1;
    }
    
    printf("socket created\n");

    serverInfos.sin_family = AF_INET;
    serverInfos.sin_addr.s_addr = inet_addr("192.168.1.141");
    serverInfos.sin_port = htons(25565);

    iSocketResult = connect(serverSocket, (SOCKADDR *)&serverInfos, sizeof(serverInfos));
    if (iSocketResult == SOCKET_ERROR)
    {
        printf("connect function failed with error: %i\n", WSAGetLastError());
        iSocketResult = closesocket(serverSocket);
        if (iSocketResult == SOCKET_ERROR)
        {
           printf("closesocket function failed with error: %i\n", WSAGetLastError());
        }
        WSACleanup();
        return -1;
    }
    printf("socket connected\n\n");
    
    printf("to send protocol = %#1.2x \nlenght = %i\n", pPacket[0], iPseudoLen);
    
    iSocketResult = send(serverSocket, pPacket , iPacketLen, 0);
    if(iSocketResult == SOCKET_ERROR)
    {
        printf("send function failed with error: %i\n", WSAGetLastError());
        iSocketResult = closesocket(serverSocket);
        if (iSocketResult == SOCKET_ERROR)
        {
           printf("closesocket function failed with error: %i\n", WSAGetLastError());
        }
        WSACleanup();
        return -1;
    }
    free(pPacket);
    
    printf("send %i (bytes) !\n\n",iSocketResult);
    
    
    iSocketResult = recv(serverSocket, handshake, 50, 0);
    if( iSocketResult == SOCKET_ERROR)
    {
        printf("recv function failed with error: %i\n", WSAGetLastError());
        iSocketResult = closesocket(serverSocket);
        if (iSocketResult == SOCKET_ERROR)
        {
           printf("closesocket function failed with error: %i\n", WSAGetLastError());
        }
        WSACleanup();
        return -1;
    }
    
    printf("response protocol = %#1.2x\nresponse lenght = %i (bytes)\n\n", handshake[0], iSocketResult);
    free(handshake);    
    
    
    iSocketResult = closesocket(serverSocket);
    if (iSocketResult == SOCKET_ERROR)
    {
        printf("closesocket function failed with error %i\n", WSAGetLastError());
        WSACleanup();
        return -1;
    }
    printf("socket disconnected.\n");
    
    WSACleanup();
    Sleep(7000);
    return 0;
}

输出控制台现在打印:

socket created
socket connected

to send protocol = 0x02 
lenght = 27
send 57 (bytes) !

response protocol = 0x02
response lenght = 37 (bytes)

socket disconnected.

感谢你们所有人!

共有1个答案

樊杰
2023-03-14

总的来说,你所做的似乎是正确的。我可以想象,当测试代码关闭它自己的套接字时,来自服务器的“连接丢失”消息就会发生。但是,看起来您没有正确地处理字符串数据类型。字符串需要以Unicode的形式发送,而且您似乎是以单字节字符的形式发送的。此外,string前面还需要有表示为2字节整数的长度。

握手字符串可能应该用wchar_t(或您喜欢的宽字符数据类型)指定如下。并在文字上使用L来指定宽字符串。以字节为单位的实际发送长度需要确保字符串长度乘以2。

wchar_t pseudo[]=L“kekos91;192.168.1.141:25565”;int pseudoLen=wcslen(pseudo);

*((short*)( packet + 1 ) = htons( pseudolLen );
memcpy( packet + 3, pseudo, pseudoLen * sizeof( wchar_t ));

在打印结果响应时,您可能需要以下内容:

printf( "Protocol response: %02x\n", handshake[0] );

然后提取字符串(协议字节后面的两个字节应该是连接哈希字符串的长度(按网络字节顺序)。所以您需要使用ntohs来提取它。然后下面的N个宽字符表示哈希。

写完所有这些之后,在我看来,您可能想要寻找一个库来处理所有的协议。我没有看过,但似乎有一些与Minecraft相关的C套接字库可用。只是胡乱猜测。再考虑一下,这取决于你的目标。如果您只是想尽可能快地构建客户机,那么寻找库肯定是有意义的。但是,如果您想学习协议、网络编程等的细节,那么按照您开始的级别编写它是一个好主意,而且会很有趣,因为您可以执行渐进的步骤,经常显示真正的结果。

 类似资料:
  • 问题内容: 在我的客户端代码中,我正在按照以下步骤连接到套接字: 创建一个套接字 连接它(失败时重试“ x”次) (填写字段后) 使用套接字进行/ 操作: recv(sockDesc, buffer, bufferLen, 0) 套接字描述符并退出 如果在/ 期间断开连接,我发现可以通过返回步骤2进行连接。 这个解决方案可以吗?我应该关闭套接字描述符并返回到步骤1吗? 我无法理解的另一个有趣的观察

  • 始终获得此错误: 我查过这些帖子 套接字失败%1

  • 问题内容: 我的Spring Boot应用程序总是在早上向我显示此whitelabel错误:无法打开JPA EntityManager进行事务;嵌套异常是javax.persistence.PersistenceException:org.hibernate.TransactionException:JDBC开始事务失败: 我在网上搜索,我认为可能是mysql关闭了8个小时的非活动连接。但是,根据

  • 在套接字最终接受另一端消失的情况下,什么指定了这个超时?是操作系统(Ubuntu 11.04),还是来自TCP/IP规范,还是套接字配置选项?

  • 问题内容: 如何创建SSL套接字连接? 我真的需要创建密钥库吗?该密钥库应该与我所有的客户端应用程序共享吗? 我用以下代码创建了一个服务器: 我用以下代码在android上创建了一个客户端: 但是当我尝试连接时,会引发以下错误: 问题答案: 您需要一个证书来建立ssl连接,您可以在密钥库中加载证书,也可以加载证书本身。我将显示一些有关keystore选项的示例。 您的代码需要一些参数才能运行: 您

  • STOMP 一种简单的消息传递协议,最初创建用于脚本语言,其框架受 HTTP 启发。 STOMP 得到广泛支持,心脏长连接一小时左右失去连接 失去到未定义的连接-建立连接后失去连接非常适合在 WebSocket 和 web 上使用。 SockJS SockJS是WebSocket技术的一种模拟,在表面上,它尽可能使用原生webSocket API,但是再底层非常智能,优先使用原生WebSocket,如果在不支持WebSocket的浏览器中,会自动降为轮询的方式。

  • 一些背景: 我有一个使用3G或4G数据连接的Android应用程序。但它也连接到一个wifi热点,以便在热点设备和应用程序之间传输一些数据。 我想做的是:创建一个到这个wifi热点的套接字连接,并通过这个套接字发送/接收数据。 我添加了以下代码,以确保我们在创建套接字时使用wifi热点wifi(否则它有时最终会使用数据连接): 这似乎没问题。但是,我在尝试连接到远程服务器地址时发现问题。下面是我正