I have created a basic client/server c++ socket program. I can write integers over the socket reliably, but when I try to write a string over the socket the receiving end only receives the data about 25% of the time. I have used Wireshark to verify that the data is being sent. I am new to c++ and network programming so any input would be appreciated. The code is below.
class compressionServer{
int PORT = 4000;
int LISTEN_QUEUE = 1024;
int sock;
int conn;
struct sockaddr_in socketAddress;
int receivedMagicData[8+1];
int receivedStatusCode[2];
int receivedPayloadLength[2];
char receivedCompressionData[2048];
int requestCode = 0;
int payloadLength;
uint32_t inBytes = 0;
uint32_t outBytes = 0;
double compressionRatio = 0;
string dataToCompress;
public:
void start(){
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("Socket Error");
exit(1);
}
bzero(&socketAddress, sizeof(socketAddress));
socketAddress.sin_family = AF_INET;
socketAddress.sin_addr.s_addr = htonl(INADDR_ANY);
socketAddress.sin_port = htons(PORT);
int enable = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0){ // so we can rebind quickly while testing
printf("setsockopt(SO_REUSEADDR) failed");
}
if(::bind(sock, (struct sockaddr *) &socketAddress, sizeof(socketAddress)) < 0){
printf("Bind Error\n");
std::cout << std::strerror(errno) << std::endl;
exit(1);
}
if(listen(sock, LISTEN_QUEUE) < 0){
printf("Listen Error");
exit(1);
}
for ( ; ; ) {
if((conn = accept(sock, (struct sockaddr *) NULL, NULL)) < 0){
printf("Accept Error");
exit(1);
}
ssize_t n;
if((n = read(conn, receivedMagicData, 8)) > 0){
int magicWord = ntohl(*receivedMagicData);
if(magicWord == 53545259){
std::cout << "DOES NOT MATCH" << std::endl;
break;
}
}
if((n = read(conn, receivedPayloadLength, 2)) > 0){
payloadLength = ntohs(*receivedPayloadLength);
std::cout << "payloadLength = " << std::hex << payloadLength << std::endl;
}
if((n = read(conn, receivedStatusCode, 2)) > 0){
requestCode = ntohs(*receivedStatusCode);
std::cout << "requestCode = " << std::hex << requestCode << std::endl;
}
while((n = read(conn, receivedCompressionData, 2048)) > 0){
receivedCompressionData[n] = 0;
cout << "data: " << receivedCompressionData << endl;
dataToCompress = receivedCompressionData;
if(strlen(receivedCompressionData) > 0){
break;
}
}
}
if (close(conn) < 0){
printf("Close Error");
exit(1);
}
}
};
The server class essential is expecting to receive 12 bytes of data as the header and after that up to 2048 bytes as the characters. This is the part only coming through a fraction of the time.
class compressionClient{
public:
void start(std::string ipAddr){
int MAX_LINE = 4096;
int sockfd;
struct sockaddr_in servaddr;
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("socket error");
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(4000);
if (inet_pton(AF_INET, ipAddr.c_str(), &servaddr.sin_addr) <= 0){
printf("inet_pton error for %s", ipAddr.c_str());
exit(1);
}
if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0){
printf("connect error");
exit(1);
}
long headerHex = htonl(0x53545259);
long header2Hex = htonl(0x31300034);
std::cout << "send: " << std::hex << headerHex << std::endl;
std::cout << "send2: " << std::hex << header2Hex << std::endl;
//server receives this
if(send(sockfd, (char *) (&headerHex), sizeof(headerHex), 0) < 0){
printf("Write Error");
exit(1);
}
//server receives this too
if(send(sockfd, (char *) (&header2Hex), sizeof(header2Hex), 0) < 0){
printf("Write Error2");
exit(1);
}
char data[100];
snprintf(data, sizeof(data), "aaabbcddd");
//server only recieves this sometimes
if(write(sockfd, data, strlen(data)) < 0){
printf("write error3");
exit(1);
}
}
};
Related
First I run the following code:
IDXGIFactory* pFactory;
HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory1), (void**)(&pFactory));
if (FAILED(hr))
{
return -1;
}
then I tried to use ffmpeg's nvenc_h264 function:
AVCodec* m_encoder = avcodec_find_encoder_by_name("h264_nvenc");
if (!m_encoder) {
m_encoder = avcodec_find_encoder_by_name("nvenc_h264");
}
if (!m_encoder) {
err = -1;
std::cout << "find 264 encoder failed" << std::endl;
return 0;
}
AVCodecContext* m_encoder_ctx = avcodec_alloc_context3(m_encoder);
if (!m_encoder_ctx) {
err = -1;
std::cout << "avcodec_alloc_context3 failed" << std::endl;
return 0;
}
m_encoder_ctx->width = 1280;
m_encoder_ctx->height = 720;
m_encoder_ctx->time_base = { 1, (int)25 };
m_encoder_ctx->codec_id = m_encoder->id;
m_encoder_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
m_encoder_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
ret = avcodec_open2(m_encoder_ctx, m_encoder, nullptr);
it's failed. the avcode_open2 would fail, it shows that
"[h264_nvenc # 0000016AE3F06F00] dl_fn->cuda_dl->cuInit(0) failed -> CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected"
but if I don't call the CreateDXGIFactory, then the avcodec_open2 would success.
I'm having trouble creating a program that will convert infix to postfix. My code is as follows:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
#define DEFAULT_SIZE 20
/*
*
*/
class Stack {
char *arr;
int tos, capacity;
public:
//Constructors
Stack();
Stack(int size);
//Destructor
~Stack();
//Methods
void push(char a);
char pop();
int get_size();
bool is_empty();
bool is_full();
void display();
char get_top();
};
Stack::Stack() {
arr = new char[DEFAULT_SIZE];
tos = 0;
capacity = DEFAULT_SIZE;
}
Stack::Stack(int size) {
arr = new char[size];
tos = 0;
capacity = size;
}
Stack::~Stack() {
delete[] arr;
}
void Stack::push(char a) {
if (!is_full())
arr[tos++] = a;
else
cout << "Sorry, the stack is full. Push failed!" << endl;
}
char Stack::pop() {
if (!is_empty())
return arr[--tos];
else {
cout << "Sorry, the stack is empty. Pop failed!" << endl;
return -1;
}
}
char Stack::get_top() {
if (!is_empty())
return arr[tos - 1];
else {
cout << "Sorry, the stack is empty. Pop failed!" << endl;
return 'E';
}
}
int Stack::get_size() {
return tos;
}
bool Stack::is_empty() {
if (tos == 0)
return true;
else
return false;
}
bool Stack::is_full() {
if (tos == capacity)
return true;
else
return false;
}
void Stack::display() {
if (tos == 0)
cout << "The stack is empty" << endl;
else {
for (int i = 0; i<tos;i++)
cout << arr[i] << " ";
cout << endl;
}
}
int main() {
Stack stack(50);
string infix = "(1+3)*2/(6-4)^2";
stringstream ss;
for (char c : infix) {
if ('0' <= c && c <= '9') {
ss << c;
}
else if (c == '(') {
continue;
}
else if (c == ')') {
ss << stack.pop();
stack.pop();
}
else if (c == '^' || c == '*' || c == '/' || c == '+' || c == '-') {
stack.push(c);
}
}
string postfix = ss.str();
cout << postfix;
I know what my issue is, I just dont understand or comprehend how to solve it. This code currently outputs 13+264-2. It needs to output 13+2*64-2^/. I know my issues is with my last else if statement in int main(). I dont understand how to rearrange the operators behind the operands.
Anything in parentheses is passed into the stream correctly, because I can wait until the closing parenthesis is hit to add in the operator. I can't visualize how to make that work for things not in parentheses though. Can anyone offer any advice?
I have a client using libwebsocket to establish a connection to a server. Whenever the client sends a request, the server sends a response and after receiving the response the client closes the connection. Works fine.
But when the server does not answer to the request i have the problem that the client keeps waiting for a response forever. When nothing happens the callback is never called and its not possible to close connection with returning -1 from callback function.
Is there any way to enable a timeout for the connection to close? Or any possibility to close connection from outside the callback function?
Here is my code so far:
int callback_function(libwebsocket_context* context, libwebsocket* wsi, enum libwebsocket_callback_reasons reason, void* user, void* in, size_t len) {
switch (reason) {
case LWS_CALLBACK_CLIENT_ESTABLISHED: {
std::cout << "LWS_CALLBACK_CLIENT_ESTABLISHED" << std::endl;
libwebsocket_callback_on_writable(context, wsi);
}
break;
case LWS_CALLBACK_CLOSED:{
std::cout << "LWS_CALLBACK_CLOSED" << std::endl;
}
break;
case LWS_CALLBACK_CLIENT_RECEIVE_PONG:
case LWS_CALLBACK_CLIENT_RECEIVE:{
std::cout << "LWS_CALLBACK_CLIENT_RECEIVE" << endl;
((char *)in)[len] = '\0';
answers_[current_request] = answers_[current_request] + string((char *)in);
if (libwebsocket_is_final_fragment(wsi)){
std::cout << "request:" << requests_[current_request] << std::endl;
std::cout << "answer:" << answers_[current_request] << std::endl;
current_request++;
if(current_request >= answers_.size()) {
ready = true;
return -1;
}
libwebsocket_callback_on_writable(context, wsi);
}
}
break;
case LWS_CALLBACK_CLIENT_WRITEABLE:{
std::cout << "LWS_CALLBACK_CLIENT_WRITEABLE" << endl;
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 4096 + LWS_SEND_BUFFER_POST_PADDING];
const std::string message = std::string(requests_[current_request]);
std::copy(message.begin(), message.end(), &buf[LWS_SEND_BUFFER_PRE_PADDING]);
buf[LWS_SEND_BUFFER_PRE_PADDING+(int)message.size()]='\0';
int n = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], (size_t)message.size(), static_cast<libwebsocket_write_protocol>(LWS_WRITE_BINARY));
if (n < 0){
std::cout << kLogErr << "bad things are happening" << std::endl;
return -1;
}
if (n < (int)message.size()) {
std::cout << kLogErr << "Partial write LWS_CALLBACK_CLIENT_WRITEABLE" << std::endl;
return -1;
}
}
break;
default:
std::cout << "CALLBACK_DEFAULT: " << reason << endl;
break;
}
return 0;
}
vector<string> sendMessage(const string& server, int port, const string& path, const vector<string>& messages, bool& error) {
ready = error = false;
current_request = 0;
requests_ = vector<string>(messages);
answers_ = vector<string>(requests_.size(), "");
int ietf_version = -1; /* latest */
wsi_ = libwebsocket_client_connect(context_, server.c_str(), port, 2, path.c_str(), server.c_str(), "origin", NULL, ietf_version);
if (wsi_ == NULL) {
std::cout << kLogErr << "libwebsocket connect failed server:" << server << " port: " << port << " path: " << path << std::endl;
error = true;
return vector<string>();
}
bool first_time = true;
int n = 0;
while (n >= 0 && !force_exit && !ready) {
n = libwebsocket_service(context_, 0);
if(first_time) {
libwebsocket_callback_on_writable(context_, wsi_);
first_time = false;
}
if (n < 0){
continue;
}
if (wsi_ == NULL) {
break;
}
}
error = !ready;
wsi_ = NULL;
return vector<string>(answers_);
}
You could try using:
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
return -1;
break;
Or
lws_set_timeout
But I'm not a 100% sure that will work, you could also try creating an issue/question on their GitHub, they tend to answer quite fast/clear.
I'm also not sure if you should implement
I solved the problem.
I programmed a timer in
vector<string> sendMessage(const string& server, int port, const string& path, const vector<string>& messages, bool& error)
and when the timeout is reaches, the timer sets a flag and triggers
libwebsocket_callback_on_writable(context_, wsi_);
again. Then in
int callback_function(libwebsocket_context* context, libwebsocket* wsi, enum libwebsocket_callback_reasons reason, void* user, void* in, size_t len)
in case
LWS_CALLBACK_CLIENT_WRITEABLE
i check the flag and if it is set the callback is aborted with
return -1;
Works fine!
I have SST files form Microsoft which I need to add to a java truststore.
The problem is all tools that Microsoft provides, add the certs from SST files to windows stores, so difficult to get PEM files form the SST files. If I run certmgr.exe (not certmgr.msc), I can get public key and all that but no cert (in pem or der), I saw bunch of VB scripts and powershell to load them using SST file into System.Security.Cryptography.X509Certificates.X509Certificate2Collection object, but still can't find a way to output as PEM (or der ) formated certificates.
Any suggestions?
S
You could use CAPI to open the SST file as a certificate store then enumerate over the certificates in the file. The following code does this and outputs the certificates in DER form to a file using a SHA1 hash of the certificate as a filename. The first argument is the output folder. The remaining one or more arguments are your SST files.
#include <stdio.h>
#include <tchar.h>
#include "windows.h"
#include "wincrypt.h"
#include "atlbase.h"
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
std::string GetHexRepresentation(const unsigned char * Bytes, size_t Length)
{
std::ostringstream os;
os.fill('0');
os<<std::hex;
for(const unsigned char * ptr=Bytes;ptr<Bytes+Length;ptr++)
os<<std::setw(2)<<(unsigned int)*ptr;
std::string retval = os.str();
std::transform(retval.begin(), retval.end(),retval.begin(), ::toupper);
return retval;
}
BOOL WriteToFileWithHashAsFilename(PCCERT_CONTEXT pPrevCertContext, TCHAR* outputDir)
{
#undef RETURN
#define RETURN(rv) \
{ \
if( hHash ) CryptDestroyHash(hHash); \
if( hProv ) CryptReleaseContext(hProv, 0); \
return rv; \
}
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
BYTE byteFinalHash[20];
DWORD dwFinalHashSize = 20;
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
std::cout << "CryptAcquireContext failed: " << GetLastError() << std::endl;
RETURN(FALSE);
}
if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
{
std::cout << "CryptCreateHash failed: " << GetLastError() << std::endl;
RETURN(FALSE);
}
if (!CryptHashData(hHash, pPrevCertContext->pbCertEncoded, pPrevCertContext->cbCertEncoded, 0))
{
std::cout << "CryptHashData failed: " << GetLastError() << std::endl;
RETURN(FALSE);
}
if (!CryptGetHashParam(hHash, HP_HASHVAL, byteFinalHash, &dwFinalHashSize, 0))
{
std::cout << "CryptGetHashParam failed: " << GetLastError() << std::endl;
RETURN(FALSE);
}
std::string strHash = GetHexRepresentation(byteFinalHash, dwFinalHashSize);
std::wostringstream filename;
filename << outputDir << strHash.c_str() << ".der" <<std::ends;
FILE* f = _wfopen(filename.str().c_str(), L"wb+");
if(!f)
{
std::wcout << "Failed to open file for writing: " << filename.str().c_str() << std::endl;
RETURN(FALSE);
}
int bytesWritten = fwrite(pPrevCertContext->pbCertEncoded, 1, pPrevCertContext->cbCertEncoded, f);
fclose(f);
if(bytesWritten != pPrevCertContext->cbCertEncoded)
{
std::cout << "Failed to write file" << std::endl;
RETURN(FALSE);
}
RETURN(TRUE);
}
//usage: DumpCertsFromSst <output directory> <SST file 1> ... <SST file n>
int _tmain(int argc, _TCHAR* argv[])
{
SECURITY_ATTRIBUTES sa;
memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = FALSE;
if(argc < 3)
{
std::cout << "At least two arguments must be provided: outputDirectory sstFile1 ... sstFileN etc" << std::endl;
return 0;
}
TCHAR* outputDir = argv[1];
for(int ii = 2; ii < argc; ++ii)
{
HANDLE hFile = NULL;
HCERTSTORE hFileStore = NULL;
LPCWSTR pszFileName = argv[ii];
//Open file
hFile = CreateFile(pszFileName, GENERIC_READ, 0, &sa, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == hFile)
{
std::wcout << "Failed to open file: " << pszFileName << std::endl;
continue;
}
else
{
std::wcout << "Processing file: " << pszFileName << std::endl;
}
//open certificate store
hFileStore = CertOpenStore(CERT_STORE_PROV_FILE, 0, NULL, CERT_STORE_READONLY_FLAG, hFile);
if(NULL == hFileStore)
{
CloseHandle(hFile);
continue;
}
int count = 0;
PCCERT_CONTEXT pPrevCertContext = NULL;
pPrevCertContext = CertEnumCertificatesInStore(hFileStore, pPrevCertContext);
while(NULL != pPrevCertContext)
{
if(WriteToFileWithHashAsFilename(pPrevCertContext, outputDir))
++count;
pPrevCertContext = CertEnumCertificatesInStore(hFileStore, pPrevCertContext);
}
std::wcout << "Wrote " << count << " certificates" << std::endl;
CloseHandle(hFile);
CertCloseStore(hFileStore, 0);
}
return 1;
}
So I'm building a multithreaded socket library in windows and I'm getting the WSA Not Started error when I call recv, even though I successfully get a client to connect to the server. I also had it working before I threaded it, but I don't know what happened since then. Any help would be appreciated.
Spocket.hpp
#include <iostream>
#include <string>
#include <Windows.h>
#pragma comment (lib,"ws2_32.lib")
static bool initialized_ = false;
class Spocket
{
protected:
WSADATA wsaData_;
SOCKET hSocket_;
sockaddr_in service_;
std::string addr_;
USHORT port_;
int exitCode_;
public:
Spocket() {
initialize();
create_socket();
}
Spocket(std::string addr, USHORT port)
: addr_( addr ), port_( port ) {
initialize();
create_socket();
}
Spocket(Spocket spock, SOCKET sock)
: hSocket_( sock ),
wsaData_( spock.wsaData_ ),
service_( spock.service_ ),
addr_( spock.addr_ ),
port_( spock.port_ )
{
initialize();
}
virtual ~Spocket() { close(); }
void initialize();
void create_socket();
void close();
template<typename T>
int recv_data(T* i) {
int ret = recv( hSocket_, reinterpret_cast<char*>(i), 32, 0 );
if( ret == SOCKET_ERROR )
cerr << WSAGetLastError() << endl;
return ret;
}
template<typename T>
int send_data(T* i) {
int ret = send( hSocket_, reinterpret_cast<char*>(i), sizeof(i), 0 );
if( ret == SOCKET_ERROR )
cerr << WSAGetLastError() << endl;
return ret;
}
};
class ServerSpocket : public Spocket
{
public:
ServerSpocket(std::string addr, USHORT port);
Spocket* accept_clients();
};
class ClientSpocket : public Spocket
{
public:
ClientSpocket(std::string addr, USHORT port);
};
Spocket.cpp
#include <iostream>
using namespace std;
#include "../include/spocket.hpp"
void Spocket::initialize() {
if(!initialized_)
{
cout << "Initializing socket..." << endl;
exitCode_ = EXIT_SUCCESS;
int iResult = WSAStartup( MAKEWORD(2,2), &wsaData_ );
if( iResult != NO_ERROR ) {
cerr << "WSAStartup failed" << endl;
exitCode_ = EXIT_FAILURE;
close();
}
initialized_ = true;
}
}
void Spocket::create_socket() {
hSocket_ = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if( hSocket_ == INVALID_SOCKET )
{
cerr << "Error at socket(): " << WSAGetLastError() << endl;
exitCode_ = EXIT_FAILURE;
close();
}
service_.sin_family = AF_INET;
service_.sin_addr.s_addr = inet_addr(addr_.c_str());
service_.sin_port = htons(port_);
}
void Spocket::close() {
closesocket( hSocket_ );
WSACleanup();
}
ServerSpocket::ServerSpocket(std::string addr, USHORT port) : Spocket(addr, port) {
if( bind( hSocket_, (SOCKADDR*)&service_, sizeof(service_) ) == SOCKET_ERROR )
{
cerr << "Failed to bind" << endl;
exitCode_ = EXIT_FAILURE;
close();
}
if( listen( hSocket_, 1 ) == SOCKET_ERROR )
{
cerr << "Error listening on socket" << endl;
exitCode_ = EXIT_FAILURE;
close();
}
}
Spocket* ServerSpocket::accept_clients() {
cout << "Waiting for connection...\n";
SOCKET hAccepted = INVALID_SOCKET;
while( hAccepted == INVALID_SOCKET )
hAccepted = accept( hSocket_, NULL, NULL );
return new Spocket( *this, hAccepted );
}
ClientSpocket::ClientSpocket(std::string addr, USHORT port) : Spocket(addr, port) {
if( connect( hSocket_, (SOCKADDR*)&service_, sizeof(service_) ) == SOCKET_ERROR )
{
cerr << "Failed to connect" << endl;
exitCode_ = EXIT_FAILURE;
close();
}
}
Server_main.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <spocket.hpp>
using namespace std;
vector<HANDLE> hThreads;
vector<DWORD> dwThreadIds;
struct ConnectionInfo
{
string ip;
unsigned int port;
ConnectionInfo( string ip_, unsigned int port_ ) : ip(ip_), port(port_){}
};
static ConnectionInfo ci( "127.0.0.1", 27015 );
DWORD WINAPI clientSession( LPVOID lpParam )
{
// create new socket to listen for connection attempts
ConnectionInfo arg = *reinterpret_cast<ConnectionInfo*>(lpParam);
ServerSpocket listenSock( arg.ip, arg.port );
// spawn a duplicate thread when a connection is made, and close the current listening socket
Spocket* sessionSock = listenSock.accept_clients();
listenSock.close();
cout << "client connected..." << endl;
/*
hThreads.push_back( CreateThread( NULL, 0, clientSession, &ci, 0, NULL ) );
*/
// service the connected client
string msg;
while( sessionSock->recv_data(&msg) != SOCKET_ERROR && msg != "goodbye!" )
{
cout << msg << endl;
msg.clear();
}
cout << "finished with client..." << endl;
// wait quietly for server shutdown
while( true )
Sleep( 200 );
return 0;
}
int main() {
cout << "[Server]" << endl;
cout << "starting up..." << endl;
hThreads.push_back( CreateThread( NULL, 0, clientSession, &ci, 0, NULL ) );
string input = "";
do
cin >> input;
while( input != "exit" );
// close all thread handles here
cout << "shutting down..." << endl;
return 0;
}
I beleive you must keep the "original" socket alive. Move listenSock.close(); after the sessionSock->recv_data() loop.