c - Socket loses connection on send() -
edit : scroll down see updated code.
i build fake player minecraft, in c language.
my minecraft server (bukkit) listening on port 25565, on local ip 192.168.1.141
when launch application, (when send data trough socket) bukkit server says : "192.168.1.141:xxxxx lost connection", and
my application tell me :
socked created socked connected send data = (smilie)kekos91;192.168.1.141:25565 send length = 27 send ! response data = (a strange symbol) response length = 1 socket disconnected maybe because of char-set ? know why ? here code :
#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 error: %d\n", iresult); return -1; } serversocket = socket(af_inet, sock_stream, ipproto_tcp); if (serversocket == invalid_socket) { printf("socket function failed 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 error: %i\n", wsagetlasterror()); iresult = closesocket(serversocket); if (iresult == socket_error) { printf("closesocket function failed 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 point, connection loose :( if(send(serversocket, (char*)packet , plenght, 0) == socket_error) { printf("send function failed error: %i\n", wsagetlasterror()); iresult = closesocket(serversocket); if (iresult == socket_error) { printf("closesocket function failed 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 error: %i\n", wsagetlasterror()); iresult = closesocket(serversocket); if (iresult == socket_error) { printf("closesocket function failed 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 error %i\n", wsagetlasterror()); wsacleanup(); return -1; } printf("socket disconnected.\n"); wsacleanup(); sleep(5000); return 0; } thanks in advance, , please excuse bad english :)
update :
thanks constructive comments, works now. here working code see going on old code.
#include <stdio.h> #include <stdlib.h> #include <windows.h> #include <winsock2.h> int main() { int isocketresult = 0; // retrieve sockets return functions, 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 error: %d\n", isocketresult); return -1; } serversocket = socket(af_inet, sock_stream, ipproto_tcp); if (serversocket == invalid_socket) { printf("socket function failed 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 error: %i\n", wsagetlasterror()); isocketresult = closesocket(serversocket); if (isocketresult == socket_error) { printf("closesocket function failed 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 error: %i\n", wsagetlasterror()); isocketresult = closesocket(serversocket); if (isocketresult == socket_error) { printf("closesocket function failed 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 error: %i\n", wsagetlasterror()); isocketresult = closesocket(serversocket); if (isocketresult == socket_error) { printf("closesocket function failed 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 error %i\n", wsagetlasterror()); wsacleanup(); return -1; } printf("socket disconnected.\n"); wsacleanup(); sleep(7000); return 0; } the output console prints :
socket created socket connected send protocol = 0x02 lenght = 27 send 57 (bytes) ! response protocol = 0x02 response lenght = 37 (bytes) socket disconnected. thanks !
in general, doing appears correct. imagine "connection lost" message server happens when test code closes own socket. however, looks not handling string data type correctly. string needs sent unicode, , appears sending single-byte characters. also, string needs preceded length represented 2 byte integer.
the handshake string should maybe instead specified follows wchar_t (or favorite wide character data type). , use l on literal specify wide string. actual send length in bytes needs sure multiply string length 2.
wchar_t pseudo[] = l"kekos91;192.168.1.141:25565"; int pseudolen = wcslen(pseudo);
then, likewise, use wide string function copy string (strcat won't work).
to put string length in 2 bytes after 0x02 protocol code, might this:
*((short*)( packet + 1 ) = htons( pseudollen ); to copy string packet, maybe (i'm writing on fly without compiling:
memcpy( packet + 3, pseudo, pseudolen * sizeof( wchar_t )); the actual send length in bytes be: 3 + pseudolen * sizeof( wchar_t )
when printing resulting response, might want:
printf( "protocol response: %02x\n", handshake[0] ); and extract string (the 2 bytes following protocol byte should length of connection hash string (in network byte order). need use ntohs extract it. , following n wide characters represent hash.
having written that, seems me might want library deal protocols. have not looked, seems there minecraft-related sockets library c available. wild guess. edit on second thought, depends on goals. if wanting build client fast possible, makes sense library. if, however, wanting learn details of protocol, network programming, etc. writing @ level started idea , lot of fun since can make incremental steps show real results quite often.
one other thing. memset after allocating memory might not doing expect. assuming 32-bit architecture, sizeof( packet ) 4 (it's 4 byte pointer). however, since filling packet in data, memset isn't necessary.
Comments
Post a Comment