Sockets Asio(C+;+;):从服务器接收数据后无法向服务器发送数据
我们正在尝试创建一个通过tcp套接字对文件进行简单修改的项目。我们使用Asio创建了向端口发送和接收数据的类:Sockets Asio(C+;+;):从服务器接收数据后无法向服务器发送数据,sockets,c++14,boost-asio,winsock,Sockets,C++14,Boost Asio,Winsock,我们正在尝试创建一个通过tcp套接字对文件进行简单修改的项目。我们使用Asio创建了向端口发送和接收数据的类: //ReceiveData.hpp #pragma once #include <string> #include <thread> #include <chrono> #include <vector> #include <asio.hpp> #include <iostream> #include "Send
//ReceiveData.hpp
#pragma once
#include <string>
#include <thread>
#include <chrono>
#include <vector>
#include <asio.hpp>
#include <iostream>
#include "SendReceiveConsts.hpp" //contains global io service object
using asio::ip::tcp;
typedef unsigned short ushort;
class ReceiveData {
private:
asio::io_service service;
tcp::acceptor acceptor;
tcp::socket socket;
public:
ReceiveData(ushort port = 8008) : acceptor(SendReceive::global_io_service, tcp::endpoint(tcp::v4(), port)),
socket(SendReceive::global_io_service) { }
// Can return any amount on the socket stream
template<size_t N>
inline std::string receive() {
std::string message;
try {
if (!this->socket.is_open()) {
this->acceptor.accept(socket);
}
SendReceive::global_io_service.run();
std::array<char, N> buf;
asio::error_code error;
size_t len = this->socket.read_some(asio::buffer(buf), error);
if(error)
throw asio::system_error(error);
std::copy(buf.begin(), buf.end(), std::back_inserter(message));
} catch(asio::error_code& e) {
std::cout << e.message() << std::endl;
return "-1";
} catch (std::exception& e) {
std::cout << e.what() << std::endl;
return "-1";
}
return message;
}
inline void stop() {
asio::error_code error;
socket.shutdown(tcp::socket::shutdown_type::shutdown_send, error);
}
};
//ReceiveData.hpp
#布拉格语一次
#包括
#包括
#包括
#包括
#包括
#包括
#包括“SendReceiveConsts.hpp”//包含全局io服务对象
使用asio::ip::tcp;
typedef无符号短ushort;
类接收数据{
私人:
asio::io_服务;
tcp::接受者-接受者;
tcp::套接字;
公众:
ReceiveData(ushort端口=8008):接受程序(SendReceive::global_io_服务,tcp::endpoint(tcp::v4(),端口)),
套接字(SendReceive::全局io_服务){}
//可以返回套接字流中的任何金额
模板
内联std::string receive(){
std::字符串消息;
试一试{
如果(!this->socket.is_open()){
此->接受程序.接受(套接字);
}
SendReceive::global_io_service.run();
std::阵列buf;
asio::错误\代码错误;
size\u t len=this->socket.read\u some(asio::buffer(buf),错误);
如果(错误)
抛出asio::系统错误(错误);
std::copy(buf.begin()、buf.end()、std::back_插入器(消息));
}捕获(asio::错误\U代码和e){
std::cout IP=IP;
此->端口=端口;
this->endpoint\u iterator=resolver.resolve(this->query);
}
~SendData(){stop();}
已弃用(无效简单_发送(std::字符串数据));
内联void发送(标准::字符串数据,常量字符和分隔符='\0'){
发送字符串(数据、分隔符);
}
内联无效停止(){
asio::错误\代码错误;
此->套接字.shutdown(tcp::套接字::shutdown\u类型::shutdown\u接收,错误);
如果(错误){
printf(“关闭SendData套接字时发生错误:%s(文件:%s,第%i行)\n”,error.message().c_str(),_文件,_行);
}
此->套接字.close();
printf(“套接字已关闭。\n”);
}
内联std::tuple get_raw_info(){
返回std::tuple(this->IP,this->port);
}
};
使用这些类,我们能够从主设备和两台从设备发送数据,这两台从设备能够可靠地接收数据。但是,主设备永远无法从从从设备接收数据。以下是主设备上运行的代码:
//HashFile.cpp
#include <string>
#include <fstream>
#include <time.h>
#include <thread>
#include <chrono>
#include <networking/SendData.hpp>
#include <networking/ReceiveData.hpp>
#include <MIST.hpp>
#include <Machine.hpp>
#define FILE_SIZE 60
std::string random_salt(std::string s) {
std::string copy = "";
std::string chars = "abcdefghijklmnopqrstufwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678910!@#$%^&*()_+-=";
for(std::string::iterator i = s.begin(); i != s.end(); i++) {
copy.push_back(*i);
srand(time(0));
if((rand() % 100) < 10) {
srand(time(0));
copy.push_back(chars.at(rand() % chars.length()));
}
}
return copy;
}
std::string add_salt(std::string s) {
std::string copy = "";
for(std::string::iterator i = s.begin(); i != s.end(); i++) {
copy.push_back(*i);
if(*i == '6') {
copy.push_back('w');
copy.push_back('h');
copy.push_back('a');
copy.push_back('t');
} else if(*i == 'c' && *i == '9' && *i == 'D') { //c9D
//HG6v
copy.pop_back();
copy.push_back(*i);
copy.push_back('G');
copy.push_back('6');
copy.push_back('v');
} else if(tolower(*i) == 'm' && tolower(*(i + 1)) == 'i') {
copy.push_back('s');
copy.push_back('t');
}
}
return copy;
}
int main() {
std::vector<MIST::Machine> machines_used = { MIST::Machine("local"), MIST::Machine("Helper 1", "25.88.30.47", false), MIST::Machine("Helper 2", "25.88.123.114", false) }; //Hamachi IP addresses
auto mist = MIST::MIST(true, machines_used);
std::ifstream hash;
std::string data1 = "";
std::string data2 = "";
std::string mydata = "";
printf("Dangerously large file being imported into code...\n");
hash.open("testfile_smol", std::fstream::binary);
if(hash.is_open()) {
try {
char chunk;
int counter = 0;
while(hash.get(chunk)) {
if(counter < FILE_SIZE / 3) {
data1 += chunk;
counter++;
} else if(counter < FILE_SIZE * (2.0f / 3.0f)) {
data2 += chunk;
counter++;
} else {
mydata += chunk;
counter++;
}
}
} catch(std::exception& e) {
std::cerr << "Error encountered: " << e.what() << std::endl;
}
}
hash.close();
printf("data1: %s data2: %s mydata: %s", data1.substr(0, 10).c_str(), data2.substr(0, 10).c_str(), mydata.substr(0, 10).c_str());
ProtobufMIST::Task task;
task.set_task_name("hash");
std::string serialized;
task.SerializeToString(&serialized);
const char c = 185;
printf("Send all!\n");
std::string s1 = "1" + data1 + c + serialized;
std::string s2 = "2" + data2 + c + serialized;
mist.send_task(s1, "Helper 1", 1025);
printf("Updated first task!\n");
mist.send_task(s2, "Helper 2", 1025); //Just a wrapper for SendData, as described in SendData.h
printf("Updated first task!\n");
std::string mydata_salted = add_salt(random_salt(mydata)); //TODO: Add pepper
printf("Old mydata size: %zu\nNew mydata size: %zu\n", mydata.length(), mydata_salted.length());
std::string one(""), two("");
unsigned short port1 = 1026;
unsigned short port2 = 1027;
auto receive_slaves = [=](unsigned short& port, std::string& out) {
bool got = false;
printf("Looking for string on port %u\n", port);
while(!got) {
auto slave = new ReceiveData(port); //As defined in ReceiveData.hpp
std::string x = slave->receive<1>();
printf("Got chunk: %s\n", x.c_str());
if(!(x.find((char)182) != std::string::npos || x == "-1")) {
out += x;
} else {
got = true;
}
delete slave;
}
printf("Received full string!\n");
};
printf("Openning both receive channels...\n");
printf("Waiting for strings...\n");
//THIS IS WHERE IT BREAKS
receive_slaves(port2, two); //Never gets response
receive_slaves(port1, one); //Never gets response
printf("Received all parts!\n");
printf("Removing delimiters...\n");
one.erase(std::remove(one.begin(), one.end(), (char)182), one.end());
two.erase(std::remove(two.begin(), two.end(), (char)182), two.end());
std::ofstream output;
output.open("Hashed");
output << one << two << mydata_salted;
output.close();
printf("Aloha!\n");
return 0;
}
//HashFile.cpp
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义文件大小为60
std::string random_salt(std::string s){
std::string copy=“”;
std::string chars=“abcdefghijklmnopqrstufxyzabcdefghijklmnopqrstuvxyz12345678910!@$%^&*()”;
for(std::string::iterator i=s.begin();i!=s.end();i++){
复制。推回(*i);
srand(时间(0));
如果((rand()%100)<10){
srand(时间(0));
复制。推回(字符数在(rand()%chars.length());
}
}
返回副本;
}
标准::字符串添加_盐(标准::字符串s){
std::string copy=“”;
for(std::string::iterator i=s.begin();i!=s.end();i++){
复制。推回(*i);
如果(*i==“6”){
复制。推回(“w”);
复制。向后推(“h”);
复制。向后推(“a”);
复制。向后推(“t”);
}else如果(*i=='c'&&&&i=='9'&&&i=='D'){//c9D
//HG6v
copy.pop_back();
复制。推回(*i);
复制。向后推(“G”);
复制。向后推(“6”);
复制。向后推(“v”);
}如果(tolower(*i)='m'&&tolower(*(i+1))=='i'){
复制。向后推(s);
复制。向后推(“t”);
}
}
返回副本;
}
int main(){
std::vector machines_used={MIST::Machine(“local”),MIST::Machine(“Helper 1”,“25.88.30.47”,false),MIST::Machine(“Helper 2”,“25.88.123.114”,false)};//滨池IP地址
自动雾化=雾化::雾化(正确,使用的机器);
std::ifstream散列;
std::string data1=“”;
std::string data2=“”;
std::string mydata=“”;
printf(“导入到代码中的危险大文件…\n”);
open(“testfile_smol”,std::fstream::binary);
if(hash.is_open()){
试一试{
炭块;
int计数器=0;
while(hash.get(chunk)){
if(计数器<文件大小/3){
data1+=chunk;
计数器++;
}else if(计数器<文件大小*(2.0f/3.0f)){
data2+=块;
计数器++;
}否则{
mydata+=chunk;
计数器++;
}
}
}捕获(标准::异常&e){
std::cerr看起来,在另一端有可用套接字之前,您在从属程序上创建了SendData,导致解析器(在创建SendData对象时运行)无法解析您使用的ip地址。请在发送数据之前尝试创建SendData
另外,ASIO的包装也很好。它可能需要一些工作,但这只是一个开始,而且它似乎比直接ASIO更简单。看起来,在另一端有可用套接字之前,您就在从属程序上创建了SendData,从而导致解析程序(在创建SendData对象时运行解析程序)无法解析您使用的ip地址。请在发送数据之前尝试创建SendData
另外,ASIO的包装也很好。它可能需要一些工作,但这只是一个开始,它似乎比直接ASIO更简单
//HashFile.cpp
#include <string>
#include <fstream>
#include <time.h>
#include <thread>
#include <chrono>
#include <networking/SendData.hpp>
#include <networking/ReceiveData.hpp>
#include <MIST.hpp>
#include <Machine.hpp>
#define FILE_SIZE 60
std::string random_salt(std::string s) {
std::string copy = "";
std::string chars = "abcdefghijklmnopqrstufwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678910!@#$%^&*()_+-=";
for(std::string::iterator i = s.begin(); i != s.end(); i++) {
copy.push_back(*i);
srand(time(0));
if((rand() % 100) < 10) {
srand(time(0));
copy.push_back(chars.at(rand() % chars.length()));
}
}
return copy;
}
std::string add_salt(std::string s) {
std::string copy = "";
for(std::string::iterator i = s.begin(); i != s.end(); i++) {
copy.push_back(*i);
if(*i == '6') {
copy.push_back('w');
copy.push_back('h');
copy.push_back('a');
copy.push_back('t');
} else if(*i == 'c' && *i == '9' && *i == 'D') { //c9D
//HG6v
copy.pop_back();
copy.push_back(*i);
copy.push_back('G');
copy.push_back('6');
copy.push_back('v');
} else if(tolower(*i) == 'm' && tolower(*(i + 1)) == 'i') {
copy.push_back('s');
copy.push_back('t');
}
}
return copy;
}
int main() {
std::vector<MIST::Machine> machines_used = { MIST::Machine("local"), MIST::Machine("Helper 1", "25.88.30.47", false), MIST::Machine("Helper 2", "25.88.123.114", false) }; //Hamachi IP addresses
auto mist = MIST::MIST(true, machines_used);
std::ifstream hash;
std::string data1 = "";
std::string data2 = "";
std::string mydata = "";
printf("Dangerously large file being imported into code...\n");
hash.open("testfile_smol", std::fstream::binary);
if(hash.is_open()) {
try {
char chunk;
int counter = 0;
while(hash.get(chunk)) {
if(counter < FILE_SIZE / 3) {
data1 += chunk;
counter++;
} else if(counter < FILE_SIZE * (2.0f / 3.0f)) {
data2 += chunk;
counter++;
} else {
mydata += chunk;
counter++;
}
}
} catch(std::exception& e) {
std::cerr << "Error encountered: " << e.what() << std::endl;
}
}
hash.close();
printf("data1: %s data2: %s mydata: %s", data1.substr(0, 10).c_str(), data2.substr(0, 10).c_str(), mydata.substr(0, 10).c_str());
ProtobufMIST::Task task;
task.set_task_name("hash");
std::string serialized;
task.SerializeToString(&serialized);
const char c = 185;
printf("Send all!\n");
std::string s1 = "1" + data1 + c + serialized;
std::string s2 = "2" + data2 + c + serialized;
mist.send_task(s1, "Helper 1", 1025);
printf("Updated first task!\n");
mist.send_task(s2, "Helper 2", 1025); //Just a wrapper for SendData, as described in SendData.h
printf("Updated first task!\n");
std::string mydata_salted = add_salt(random_salt(mydata)); //TODO: Add pepper
printf("Old mydata size: %zu\nNew mydata size: %zu\n", mydata.length(), mydata_salted.length());
std::string one(""), two("");
unsigned short port1 = 1026;
unsigned short port2 = 1027;
auto receive_slaves = [=](unsigned short& port, std::string& out) {
bool got = false;
printf("Looking for string on port %u\n", port);
while(!got) {
auto slave = new ReceiveData(port); //As defined in ReceiveData.hpp
std::string x = slave->receive<1>();
printf("Got chunk: %s\n", x.c_str());
if(!(x.find((char)182) != std::string::npos || x == "-1")) {
out += x;
} else {
got = true;
}
delete slave;
}
printf("Received full string!\n");
};
printf("Openning both receive channels...\n");
printf("Waiting for strings...\n");
//THIS IS WHERE IT BREAKS
receive_slaves(port2, two); //Never gets response
receive_slaves(port1, one); //Never gets response
printf("Received all parts!\n");
printf("Removing delimiters...\n");
one.erase(std::remove(one.begin(), one.end(), (char)182), one.end());
two.erase(std::remove(two.begin(), two.end(), (char)182), two.end());
std::ofstream output;
output.open("Hashed");
output << one << two << mydata_salted;
output.close();
printf("Aloha!\n");
return 0;
}
//HashFile.cpp (Slave)
#include <string>
#include <fstream>
#include <thread>
#include <chrono>
#include <time.h>
#include <MIST.pb.h>
#include <networking/SendData.hpp>
#include <networking/ReceiveData.hpp>
#include <MIST.hpp>
#include <Machine.hpp>
#include <stdlib.h>
std::string data;
std::string task;
std::string firstTwoChars;
ProtobufMIST::Task _task;
const char d = 182;
const char d_spc = 185;
int part;
std::string random_salt(std::string s) {
std::string copy = "";
std::string chars = "abcdefghijklmnopqrstufwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678910!@#$%^&*()_+-=";
for (std::string::iterator i = s.begin(); i != s.end(); i++) {
copy.push_back(*i);
srand(time(0));
if ((rand() % 100) < 10) {
srand(time(0));
copy.push_back(chars.at(rand() % chars.length()));
}
}
return copy;
}
std::string add_salt(std::string s) {
std::string copy = "";
for (std::string::iterator i = s.begin(); i != s.end(); i++) {
copy.push_back(*i);
if (*i == '6') {
copy.push_back('w');
copy.push_back('h');
copy.push_back('a');
copy.push_back('t');
}
else if (*i == 'c' && *i == '9' && *i == 'D') { //c9D
copy.pop_back();
copy.push_back(*i);
copy.push_back('G');
copy.push_back('6');
copy.push_back('v');
}
else if (tolower(*i) == 'm' && tolower(*(i + 1)) == 'i') {
copy.push_back('s');
copy.push_back('t');
}
}
return copy;
}
//Previously defined salting functions
void hash()
{
data = random_salt(data); //randomly salt
data = add_salt(data); //add random chars
}
int main()
{
MIST::Task taskThing("hash", *hash);
ReceiveData * rObj = new ReceiveData(1025);
SendData sObj("25.88.220.173", 1027);
std::cout << "Receiving first char \n";
firstTwoChars = rObj->receive<1>();
//delete rObj;
std::cout << firstTwoChars << std::endl;
std::cout << "Received first char \n";
int slavePart;
if (firstTwoChars == "1") {
slavePart = 1;
}
else if (firstTwoChars == "2") {
slavePart = 2;
}
else
std::cout << "You messed up, what part is it? \n";
std::cout << "Is part " << slavePart << std::endl;
bool dataRecieved = false;
while (!dataRecieved)
{
std::string chunk = rObj->receive<1>();
if (chunk == "-1" || chunk.find((char)182) != std::string::npos) {
std::cout << "Data recieved \n";
dataRecieved = true;
}
else
{
data += chunk;
std::cout << "Added chunk: " << chunk << std::endl;
}
chunk.clear();
}
std::cout << "All Data recieved! \n Parsing now \n";
if (data.find(d_spc) != std::string::npos)
{
size_t data_before = data.find(d_spc); //find where data ends and task begins
std::cout << "Data found at " << data_before << "bytes. \n";
std::string task = data.substr(data_before); //copy task to new string
std::cout << "Task copied: " << task << std::endl;
data.erase(data_before);//erase everything that was the task from it's original string
}
else {
std::cout << "Did not find d_spc \n";
std::abort();
}
std::cout << "Data parsed \n Data: \n";
std::cout << data << std::endl;
std::cout << "Task: " << task << std::endl;
if (_task.ParseFromString(task))
{
std::cout << "Task parsed properly \n";
}
else {
std::cout << "I messed up parsing, trying again \n";
if (_task.ParseFromString(task)) {
task.pop_back();
std::cout << "Worked the second time! \n";
}
else {
std::cout << "Still messed up \n";
std::abort();
}
}
if(_task.task_name() == "hash")
taskThing.run();
std::cout << taskThing.getID();
std::cout << "Sending... \n";
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::string t_str = std::to_string(slavePart) + data;
//THIS IS WHERE IT BREAKS
sObj.send(t_str, d); //error
int x;
std::cin >> x;
std::cout << "Sent! \n";
}