c++ - 用C语言socket登入斗鱼弹幕服务器的问题

【字号: 日期:2023-04-16浏览:26作者:雯心

问题描述

根据斗鱼给的开发者手册,用struct构建出应用层协议头,发送登入请求,建立连接成功但没有从服务器传回有效消息。代码不长,边学socket边写的注释。抓包显示成功的建立了连接,图片放在最后。

#include <stdio.h>#include <stdlib.h>#include <winsock2.h>#pragma comment (lib, 'ws2_32.lib')char* getIP() { struct hostent *host = gethostbyname('openbarrage.douyutv.com'); if (!host) {printf('Get ip errorn');system('pause');exit(0); } return inet_ntoa(*(struct in_addr*)host->h_addr_list[0]);}struct postData{ int data_len;//4字节 int data_len_2;//4字节 short message = 689;//2字节 char secreat = 0;//1字节 char presv = 0;//1字节 char body[31] = 'type@=loginreq/roomid@=846805/';};int main() { WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); //初始化 SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //创建socket //SOCKADDR为通用结构体,同时处理IPv4和IPv6 //sockaddr_in为IPv4的结构体 sockaddr_in6为IPv6的结构体 //SOCKADDR中IP地址和端口在一起,强制转换类型时转换 sockaddr_in sockAddr; memset(&sockAddr, 0, sizeof(sockAddr)); sockAddr.sin_family = PF_INET; //类型:IPv4 sockAddr.sin_addr.s_addr = inet_addr('123.150.206.162');//getIP()返回 /*sin_addr为结构体struct in_addr{in_addr_t s_addr; //32位的IP地址 }; */ sockAddr.sin_port = htons(8601); connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));postData post_Data; post_Data.data_len = sizeof(post_Data); post_Data.data_len_2 = sizeof(post_Data); send(sock, (char*)&post_Data, sizeof(postData), 0); printf('发送成功,接收中'); char bufRec[10000]; recv(sock, bufRec, sizeof(bufRec), 0); printf('Message form server: %sn', bufRec); closesocket(sock); //终止使用 DLL WSACleanup(); system('pause'); return 0;}

协议组成 众所周知,受 TPC 最大传输单元(MTU)限制及连包机制影响,应用层协议需自己设计协议头,以保证丌同消息的隔离性和消息完整性。斗鱼后台协议头 设计如下: c++ - 用C语言socket登入斗鱼弹幕服务器的问题

c++ - 用C语言socket登入斗鱼弹幕服务器的问题

登录请求消息 该消息用于完成登陆授权,完整的数据部分应包含的字段如下: type@=loginreq/roomid@=301712/ 字段说明 type 表示为“登陆请求”消息,固定为 loginreq roomid 所登录房间的 ID

服务端消息格式 服务端端向客户端发送消息时,头部消息类型字段为 690。2.4.1 登录响应消息 服务端返回登陆响应消息,完整的数据部分应包含的字段如下: type@=loginres/userid@=0/roomgroup@=0/pg@=0/sessionid@=0/username@=/nickname@=/is_signined@=0/signin_count@=0/live_stat@=0/npv@=0/best_dlev@=0/cur_lev@=0/

c++ - 用C语言socket登入斗鱼弹幕服务器的问题

问题解答

回答1:

你这个结构体的大小,并不是你发送数据的长度。具体原因请参考结构体对齐相关内容。

struct postData{ int data_len;//4字节 int data_len_2;//4字节 short message = 689;//2字节 char secreat = 0;//1字节 char presv = 0;//1字节 char body[31] = 'type@=loginreq/roomid@=846805/';};

上面结构体的sizeof结果可能是4+4+2+1+1 + 32 = 44。最后的body会对齐到32字节。

我用下面的代码测试了一下,连接不上。

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdint.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <errno.h>struct postData{ int32_t data_len;//4字节 int32_t data_len_2;//4字节 int16_t message;//2字节 int8_t secreat; //1字节 int8_t presv; //1字节 char body[0]; // = 'type@=loginreq/roomid@=846805/';};int main(){ int fd; struct sockaddr_in addr; if((fd = socket(AF_INET,SOCK_STREAM,0)) == -1){perror('socket');return -1; } memset(&addr,0,sizeof addr); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr('123.150.206.162'); addr.sin_port = htons(8601); if(connect(fd,(struct sockaddr*)&addr,sizeof addr) == -1){perror('connect'); // 连接出错,输出 connect: Connection refusedreturn -2; } struct postData* pdata = (struct postData*)malloc(64); strcpy(pdata->body,'type@=loginreq/roomid@=846805/'); pdata->data_len = pdata->data_len_2 = sizeof(*pdata) + strlen(pdata->body) +1; printf('pdata->data_len = %dn',pdata->data_len); pdata->message = 689; pdata->secreat = pdata->presv = 0;if(send(fd,pdata,pdata->data_len,0) != pdata->data_len){puts('send 未完成');return -3; } char buf[1024]; if(recv(fd,buf,sizeof(buf),0) == -1){perror('recv');return -4; } printf('接收到数据:%sn',buf);close(fd); return 0;}回答2:

早上又试了下,因为斗鱼它说除了登入请求还有其他的一些心跳检测,入组请求之类的,我都发送一遍后倒是有回应

type@=error/code@=51/.

应该是我结构体的构造有问题吧,C语言很多小东西不扎实,不是Socket的问题~

回答3:

首先,body体官方不是说了有个’0’吗?所以你发的消息的这个body数组至少也得32吧。从性能以及内部内存对齐来考虑的话,不要吝惜这一点点存储空间,用 N * PAGE_SIZE的数组大小更好一点吧。

回答4:

请问你是在看的什么书学的,怎么用到斗鱼了?

相关文章: