Restarting a UDP socket to accept DTLS connection not working - c

I am starting a UDP Server and then accepting a DTLS connection to read incoming data. The code is working fine. But once I reuse the connection from the client by restarting the client socket Server is unable to read anything. Using Cyassl library for SSL instance creation.
In Client:
Socket Binding and DTLS initialisation is fine as it is re-using the DTLS context used earlier.
In Server:
Also the socket closing and starting everything is fine but still I am unable to receive in the accepted FD.
But if I put a sleep of exactly 5 seconds between closing and starting the UDP server everything is fine. But I don't want to use blocking I/O like the sleep.
Please do help.
Server:
Accepting data received in m_udp_fd:
if(FD_ISSET(m_udp_fd, &rfds))
{
if(m_accepted_flag==0)
{
udp_read_connect(m_udp_fd);
open_dtls_server();
if(m_ssl_accept(m_udp_fd)>0)
{
media_accepted_flag = 1;
}
}
else
{
// Read data
if(process_dtls_packet(m_udp_fd)<=0)
{
//Clear FD here
}
}
}
Place where the connection is broken depending whether TCP connection is broken or not.
This is getting hit perfectly:
if (FD_ISSET(m_fd, &rfds))
{
if(process_msg(m_fd)<=0)
{
closesocket(m_fd);
FD_CLR(m_fd,recv_fds);
if(recv_fdmax == m_fd)
{
recv_fdmax = max(x_fd,y_fd);
recv_fdmax = max(recv_fdmax,z_fd);
recv_fdmax = max(recv_fdmax,p_fd);
recv_fdmax = max(recv_fdmax,q_fd);
}
}
if(m_accepted_flag!=0)
{
m_accepted_flag = 0;
x_accepted_flag = 0;
//This sleep when kept works perfectly
Sleep(5000);
close_m_and_x_connection(&recv_fdmax,recv_fds,&m_udp_fd,&x_udp_fd);
}
}
UDP Read Connect Function:
int udp_read_connect(SOCKET sockfd)
{
struct sockaddr cliaddr;
char b[1500];
int n;
int len = sizeof(cliaddr);
n = (int)recvfrom(sockfd, (char*)b, sizeof(b), MSG_PEEK,
(struct sockaddr*)&cliaddr, &len);
if (n > 0)
{
if (connect(sockfd, (const struct sockaddr*)&cliaddr,sizeof(cliaddr)) != 0)
printf("udp connect failed");
}
else
printf("recvfrom failed");
return sockfd;
}
Open DTLS Server Method: Here dtls_ctx and dtls_meth are global variables.
int open_dtls_server()
{
int verify_flag = OFF;
int error;
if(dtls_ctx!= NULL)
return;
dtls_ctx = ssl_create_context(DTLS_V1, &dtls_meth);
dtls_meth = CyaDTLSv1_server_method();
if(dtls_meth==NULL)
{
return -1;
}
dtls_ctx = CyaSSL_CTX_new(dtls_meth);
if(NULL == dtls_ctx)
{
ERR_print_errors_fp(stderr);
return -1;
}
if((status = LoadSSLCertificate(dtls_ctx,sslInfo,&error,0)) == 1)
{
return 0;
}
else
return 1;
if(CyaSSL_CTX_use_PrivateKey_file(dtls_ctx, SSL_SERVER_RSA_KEY, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
return -1;
}
if(CyaSSL_CTX_check_private_key(dtls_ctx) != 1)
{
return -1;
}
if(verify_flag)
{
if(!CyaSSL_CTX_load_verify_locations(dtls_ctx, SSL_SERVER_RSA_CA_CERT, NULL))
{
ERR_print_errors_fp(stderr);
return -1;
}
CyaSSL_CTX_set_verify(dtls_ctx, SSL_VERIFY_PEER, NULL);
}
CyaSSL_CTX_set_options(dtls_ctx, SSL_OP_ALL);
return 1;
}
m_ssl_accept Function: ssl_m is also a global variable.
int m_ssl_accept(int confd)
{
int ret;
if(ssl_m==NULL)
{
ssl_m = CyaSSL_new(dtls_ctx);
if (ssl_m == NULL)
printf("SSL_new failed");
CyaSSL_set_fd(ssl_m, confd);
}
do
{
if((ret = CyaSSL_accept(ssl_m))!= 1)
{
printf("Handshake Error on M Channel %d with FD: [%d]\n",
return -1;
}
}while(ret != 1);
return 1;
}

Related

How to send properly files in a client-server application?

I want to make a client-server application when a client can register, login, broadcast a message to another clients, send files and so on. Everything, except sending files works pretty well.
In the client application I made a separate thread for every file that I want to send. Reading the file is successful, but sending is not that good. I should make a thread in server project for receiving the bytes sent by the client?
I want sending files to be asynchronous, so that another clients can communicate with server when server is receiving a file.
The thread for reading file and sending data to server:
DWORD WINAPI SendFile(LPVOID param)
{
FileStruct* fileStruct = (FileStruct*)param;
CM_DATA_BUFFER* dataToSend = NULL;
CM_SIZE dataToSendSize = MAXLENGTH;
CM_ERROR error;
CM_SIZE sendBytesCount = 0;
FILE* f = fopen(fileStruct->filePath, "rb");
char buffer[2];
fseek(f, 0, SEEK_SET);
if (f == NULL)
{
perror((const char*)f);
}
char messageBuffer[10];
while (fread(buffer, 1, 1, f) == 1)
{
*(int*)messageBuffer = SENDTYPE;
messageBuffer[4] = buffer[0];
messageBuffer[5] = 0;
dataToSend = NULL;
error = CreateDataBuffer(&dataToSend, dataToSendSize);
if (CM_IS_ERROR(error))
{
_tprintf_s(TEXT("Failed to create SEND data buffer with err-code=0x%X!\n"), error);
DestroyClient(fileStruct->client);
UninitCommunicationModule();
return (DWORD)-1;
}
error = CopyDataIntoBuffer(dataToSend, (const CM_BYTE*)messageBuffer, (CM_SIZE)strlen(messageBuffer));
if (CM_IS_ERROR(error))
{
_tprintf_s(TEXT("CopyDataIntoBuffer failed with err-code=0x%X!\n"), error);
DestroyDataBuffer(dataToSend);
DestroyClient(fileStruct->client);
UninitCommunicationModule();
return (DWORD)-1;
}
error = SendDataToServer(fileStruct->client, dataToSend, &sendBytesCount);
if (CM_IS_ERROR(error))
{
_tprintf_s(TEXT("SendDataToServer failed with err-code=0x%X!\n"), error);
DestroyDataBuffer(dataToSend);
DestroyClient(fileStruct->client);
UninitCommunicationModule();
return (DWORD)-1;
}
DestroyDataBuffer(dataToSend);
}
return (DWORD)0;
}
Here is a part of code from Thread Server responsible for receiving data :
while ((error = ReceiveDataFromClient(newClient, receivedData, &numberOfBytesRead)) == 0)
{
message = (char*)receivedData->DataBuffer;
if (CM_IS_ERROR(error))
{
_tprintf_s(TEXT("ReceiveDataFormServer failed with err-code=0x%X!\n"), error);
DestroyDataBuffer(sendData);
DestroyDataBuffer(receivedData);
break;
}
type = *(int*)receivedData->DataBuffer;
printf("%x\n", type);
if (type == SENDTYPE)
{
printf("%c", (char)receivedData->DataBuffer[4]);
DestroyDataBuffer(receivedData);
receivedData = NULL;
error = CreateDataBuffer(&receivedData, MAXLENGTH);
if (CM_IS_ERROR(error))
{
_tprintf_s(TEXT("Creating receivedDataBuffer failed with err-code =0x%X!\n"), error);
UninitCommunicationModule();
}
continue;
}
This is ReceiveDataFromClient function:
CM_ERROR ReceiveDataFromClient(CM_SERVER_CLIENT* Client, CM_DATA_BUFFER* DataBufferToReceive, CM_SIZE* SuccessfullyReceivedBytesCount)
{
if (Client == NULL || DataBufferToReceive == NULL || SuccessfullyReceivedBytesCount == NULL)
return CM_INVALID_PARAMETER;
CM_ERROR error = ReceiveData(
Client->ClientConnection
, DataBufferToReceive->DataBuffer
, DataBufferToReceive->DataBufferSize
, SuccessfullyReceivedBytesCount
);
if (CM_IS_ERROR(error))
return error;
DataBufferToReceive->UsedBufferSize = *SuccessfullyReceivedBytesCount;
return error;
}
And this is ReceiveData function:
CM_ERROR ReceiveData(CM_CONNECTION* Connection, CM_BYTE* OutputDataBuffer, CM_SIZE OutputDataBufferSize, CM_SIZE* SuccessfullyReceivedBytesCount)
{
if (Connection == NULL)
return CM_INVALID_CONNECTION;
if (INVALID_SOCKET == Connection->ConnectionSocket)
return CM_INVALID_PARAMETER;
int receiveResult = recv(Connection->ConnectionSocket, (char*) OutputDataBuffer, OutputDataBufferSize, 0);
if (receiveResult == SOCKET_ERROR)
{
CM_LOG_ERROR(TEXT("recv failed with err-code=0x%X!"), WSAGetLastError());
return CM_CONNECTION_RECEIVE_FAILED;
}
if (receiveResult == 0)
return CM_CONNECTION_TERMINATED;
*SuccessfullyReceivedBytesCount = (CM_SIZE)receiveResult;
return CM_SUCCESS;
}

Create HTTP GET in C return 301 redirect using IP address

I want to send a GET request to a page and retrieve it to use later to a crawler
I have implemented my own D.N.S. resolver (like DIG command in LINUX) and I want to use the ip address to get the http page
I have the following code
typedef struct http_request
{
request_type req_type;
char* ip;
int port_number;
char* path;
char* data;
char* hostname;
}http_request;
typedef struct http_response
{
char* raw_response;
int status_code;
char* status_text;
char* body;
char* server_name;
int content_length;
char* content_type;
}http_response;
// main method
http_response* send_http_request(http_request* request) {
if (request == NULL) {
printf("HTTP request is NULL.\n");
return NULL;
}
http_response* response = (http_response*) malloc(sizeof(http_response));
if (response == NULL) {
exit(1);
return NULL;
}
char http_request_buffer[REQUEST_BUFF_SIZE];
memset(http_request_buffer, 0, REQUEST_BUFF_SIZE);
sprintf(http_request_buffer, "GET /%s HTTP/1.1\r\nHost:%s\r\n\r\n",
request->path, request->ip);
process_http_request(request, http_request_buffer, response);
return response;
}
static int process_http_request(http_request* request,
char* http_request_buffer, http_response* response) {
int socketfd;
struct sockaddr_in socket_details;
char temp_buffer[TEMP_BUFF_SIZE];
char* http_response_buffer;
ssize_t bytes_sent = 0;
ssize_t total_bytes_sent = 0;
ssize_t bytes_received = 0;
ssize_t total_bytes_received = 0;
int status;
http_response_buffer = (char*) malloc(RESPONSE_BUFF_SIZE);
if (http_response_buffer == NULL) {
printf(
"process_http_request: memory allocation failed for response buffer.\n");
return HTTP_ERROR_MEM_ALLOC_FAILED;
}
memset(http_response_buffer, 0, RESPONSE_BUFF_SIZE);
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd == -1) {
printf("process_http_request: socket creation failed.\n");
return HTTP_ERROR_SOCKET_CREATION_FAILED;
}
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
if (setsockopt(socketfd, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout,
sizeof(timeout)) < 0)
printf("process_http_request: socket option setting failed.\n");
bzero(&socket_details, sizeof(socket_details));
socket_details.sin_family = AF_INET;
socket_details.sin_addr.s_addr = inet_addr(request->ip);
socket_details.sin_port = htons(request->port_number);
if (connect(socketfd, (struct sockaddr*) &socket_details,
sizeof(struct sockaddr)) == -1) {
printf("process_http_request: Could not connect to the server.\n");
return HTTP_ERROR_SERVER_CONN_FAILED;
}
while (1) {
bytes_sent = send(socketfd, http_request_buffer,
strlen(http_request_buffer), 0);
if (bytes_sent < 0) {
printf("process_http_request: error writing on socket\n");
close(socketfd);
return HTTP_ERROR_SOCKET_WRITE_FAILED;
} else {
printf(
"process_http_request: wrote %d bytes data on socket successfully.\n",
(int) bytes_sent);
}
total_bytes_sent += (int) bytes_sent;
printf("process_http_request: total bytes sent = %d\n",
(int) total_bytes_sent);
if (total_bytes_sent == strlen(http_request_buffer))
break;
}
while (1) {
printf("process_http_request: receiving bytes from server\n");
memset(temp_buffer, 0, TEMP_BUFF_SIZE);
bytes_received = recv(socketfd, temp_buffer, TEMP_BUFF_SIZE, 0);
if (bytes_received == -1) {
if (total_bytes_received == 0) {
printf(
"process_http_request: Data could not be received from socket.\n");
close(socketfd);
return HTTP_ERROR_REC_FAILED;
} else {
printf(
"process_http_request: Timeout waiting for more data.\n");
break;
}
} else if (bytes_received > 0) {
sprintf(http_response_buffer, "%s%s", http_response_buffer,
temp_buffer);
total_bytes_received += bytes_received;
printf("process_http_request: total bytes received = %d\n",
(int) total_bytes_received);
}
if (bytes_received == 0) {
printf("process_http_request: Data receiving finished.\n");
close(socketfd);
break;
}
}
printf("raw buffer=%s", http_response_buffer);
response->raw_response = http_response_buffer;
status = process_http_response(http_response_buffer, response);
if (status == SUCCESS)
printf("process_http_request: HTTP response parsed successfully.\n");
else
printf(
"process_http_request: HTTP response parsing encountered problem. \n");
return status;
}
The problem is that in almost all cases return me a page with 301 redirect and a link .For example for google's ip return me a redirect page to http://www.google.com/ , and I want the page itself and I don't know what to do.
Someone please help.Thank you!

"bad packet length" error after updating to OpenSSL 0.9.8.zf

I was using OpenSSL version 0.9.8h in an Android project. I update it to the 0.9.8.zf version but now it doesn't work.
The two functions that highlight the problem are initialize_client_ctx and initialize_client_ctx. When I call SSL_connect I get an SSL_ERROR_SSL error value. By checking details I retrieve a "bad packet length" error (error:14092073:SSL routines:SSL3_GET_SERVER_HELLO:bad packet length).
The point in the code is indicated in a comment. The code works well with the previous version. I attach also a Wireshark capture file. Any ideas?
SSL_CTX *initialize_client_ctx(const char *keyfile, const char *certfile,
const char *password, int transport)
{
SSL_METHOD *meth = NULL;
X509 *cert = NULL;
SSL_CTX *ctx;
if (transport == IPPROTO_UDP) {
meth = DTLSv1_client_method();
} else if (transport == IPPROTO_TCP) {
meth = TLSv1_client_method();
} else {
return NULL;
}
ctx = SSL_CTX_new(meth);
if (ctx == NULL) {
//print ... Couldn't create SSL_CTX
return NULL;
}
if (password[0] != '\0') {
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) password);
SSL_CTX_set_default_passwd_cb(ctx, password_cb);
}
if (tls_client_local_cn_name[0] != '\0') {
cert = _tls_set_certificate(ctx, tls_client_local_cn_name);
}
if (cert==NULL && certfile[0] != '\0') {
//print several warnings....
}
if (cert!=NULL)
{
X509_free(cert);
cert = NULL;
}
/* Load the CAs we trust */
{
char *caFile = 0, *caFolder = 0;
int fd = open(eXosip_tls_ctx_params.root_ca_cert, O_RDONLY);
if (fd >= 0) {
struct stat fileStat;
if (fstat(fd, &fileStat) < 0) {
} else {
if (S_ISDIR(fileStat.st_mode)) {
caFolder = eXosip_tls_ctx_params.root_ca_cert;
} else {
caFile = eXosip_tls_ctx_params.root_ca_cert;
}
}
close(fd);
}
{
int verify_mode = SSL_VERIFY_PEER;
SSL_CTX_set_verify(ctx, verify_mode, &verify_cb);
SSL_CTX_set_verify_depth(ctx, ex_verify_depth + 1);
}
}
SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
SSL_OP_CIPHER_SERVER_PREFERENCE);
if(!SSL_CTX_set_cipher_list(ctx,"ALL")) {
//print ... set_cipher_list: cannot set anonymous DH cipher
SSL_CTX_free(ctx);
return NULL;
}
return ctx;
}
static int _tls_tl_ssl_connect_socket(struct socket_tab *sockinfo)
{
X509 *cert;
BIO *sbio;
int res;
if (sockinfo->ssl_ctx == NULL) {
sockinfo->ssl_ctx =
initialize_client_ctx(eXosip_tls_ctx_params.client.priv_key,
eXosip_tls_ctx_params.client.cert,
eXosip_tls_ctx_params.client.priv_key_pw,
IPPROTO_TCP);
sockinfo->ssl_conn = SSL_new(sockinfo->ssl_ctx);
if (sockinfo->ssl_conn == NULL) {
return -1;
}
sbio = BIO_new_socket(sockinfo->socket, BIO_NOCLOSE);
if (sbio == NULL) {
return -1;
}
SSL_set_bio(sockinfo->ssl_conn, sbio, sbio);
}
do {
struct timeval tv;
int fd;
fd_set readfds;
res = SSL_connect(sockinfo->ssl_conn);
res = SSL_get_error(sockinfo->ssl_conn, res);
if (res == SSL_ERROR_NONE) {
//printf... SSL_connect succeeded
break;
}
if (res != SSL_ERROR_WANT_READ && res != SSL_ERROR_WANT_WRITE) {
//<-- here there is a problem res == SSL_ERROR_SSL
//print ERR_reason_error_string(ERR_get_error()));
//print ERR_error_string(ERR_get_error(), NULL));
return -1;
}
tv.tv_sec = SOCKET_TIMEOUT / 1000;
tv.tv_usec = (SOCKET_TIMEOUT % 1000) * 1000;
//retry the connection
fd = SSL_get_fd(sockinfo->ssl_conn);
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
res = select(fd + 1, &readfds, NULL, NULL, &tv);
if (res < 0) {
//print error
return -1;
} else if (res > 0) {
//print...connetrion done!
} else {
//socket timeout, no data to read
return 1;
}
} while (!SSL_is_init_finished(sockinfo->ssl_conn));
if (SSL_is_init_finished(sockinfo->ssl_conn)) {
//print.. SSL_is_init_finished done
} else {
//print.. failed
}
cert = SSL_get_peer_certificate(sockinfo->ssl_conn);
if (cert != 0) {
int cert_err;
tls_dump_cert_info("tls_connect: remote certificate: ", cert);
cert_err = SSL_get_verify_result(sockinfo->ssl_conn);
if (cert_err != X509_V_OK) {
//print... Failed to verify remote certificate
tls_dump_verification_failure(cert_err);
if (eXosip_tls_ctx_params.server.cert[0] != '\0') {
X509_free(cert);
return -1;
} else if (cert_err != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
&& cert_err != X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
&& cert_err != X509_V_ERR_CRL_HAS_EXPIRED
&& cert_err != X509_V_ERR_CERT_HAS_EXPIRED
&& cert_err != X509_V_ERR_CERT_REVOKED
&& cert_err != X509_V_ERR_CERT_UNTRUSTED
&& cert_err != X509_V_ERR_CERT_REJECTED) {
X509_free(cert);
return -1;
}
}
X509_free(cert);
} else {
//print .. No certificate received
/* X509_free is not necessary because no cert-object was created -> cert == NULL */
if (eXosip_tls_ctx_params.server.cert[0] == '\0') {
#ifdef ENABLE_ADH
/* how can we guess a user want ADH... specific APIs.. */
sockinfo->ssl_state = 3;
return 0;
#endif
}
return -1;
}
sockinfo->ssl_state = 3;
return 0;
}
SOLVED Thanks to Eric Tsui that helps me to figure out the problem. The 'hello' that I receive from the server in the handshake has zero length. To solve this I modified the file openssl/ssl/s3_clnt.c in the following way (toggling off the length control):
diff -ur ./s3_clnt.c ./original/s3_clnt.c
--- submodules/externals/openssl/ssl/s3_clnt.c 2015-06-29 14:59:56.723462992 +0200
+++ ../../opensslOrig/s3_clnt.c 2015-06-29 15:00:22.487464221 +0200
## -868,12 +868,14 ##
}
#endif
+#ifndef OPENSSL_NO_TLSEXT
if (p != (d + n)) {
/* wrong packet length */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, SSL_R_BAD_PACKET_LENGTH);
goto f_err;
}
+#endif
return (1);
f_err:

wxWidgets: Client connects to the server, but the server does not recognize

I'm creating (at the time, to learn how) two applications console: a server and a client.
The client can connect to the server. If the server is not available, the application terminates with error.
The server waits make a connection, on line socketServer->Accept(1);. When the client connects, the code continues.. The problem is that the "if" following (if (socketServer->IsConnected()) {) evaluates to false.
Full source
Client
#include <wx/wxprec.h>
#include <wx/cmdline.h>
#include <wx/socket.h>
#include <wx/app.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
static const wxCmdLineEntryDesc cmdLineDesc[] = {
{ wxCMD_LINE_SWITCH, "h", "help", "show this help message",
wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
{ wxCMD_LINE_OPTION, "ip", NULL, "set ip; the default values is 127.0.0.1", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
{ wxCMD_LINE_OPTION, "p", "port", "set port; the default values is 3000", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
{ wxCMD_LINE_NONE }
};
int main(int argc, char **argv) {
// Startup
wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "program");
wxInitializer initializer;
if (!initializer) {
fprintf(stderr, "Failed to initialize the wxWidgets library, aborting.\n");
return -1;
}
// Default variables
wxString ip = "127.0.0.1";
wxString port = "3000";
// Parse
wxCmdLineParser parser(cmdLineDesc, argc, argv);
switch (parser.Parse()) {
case -1:
return 0;
break;
case 0:
parser.Found("ip", &ip);
parser.Found("p", &port);
break;
default:
break;
}
// Socket
wxPrintf("Creating socket...\n");
wxSocketClient *socketClient = new wxSocketClient(wxSOCKET_NONE);
wxPrintf("Addressing...\n");
wxPrintf("Usando ip %s\n", ip);
wxIPV4address addr;
if (!addr.Hostname(ip)) {
wxPrintf("Could not set hostname !\n");
return 1;
}
wxPrintf("Usando porta %s\n", port);
if (!addr.Service(port)) {
wxPrintf("Could not set service !\n");
return 1;
}
wxPrintf("Trying to make connection...\n");
if (socketClient->Connect(addr, true)) {
wxPrintf("Success\n");
} else {
wxPrintf("Error!\n");
return 1;
}
// Tell the server which test we are running
wxPrintf("Sending...\n");
unsigned char c = 0xDE;
socketClient->Write(&c, 1);
// This test also is similar to the first one but it sends a
// large buffer so that wxSocket is actually forced to split
// it into pieces and take care of sending everything before
// returning.
socketClient->SetFlags(wxSOCKET_WAITALL);
// Note that len is in kbytes here!
const unsigned char len = 32;
wxCharBuffer buf1(len * 1024);
for (size_t i = 0; i < len * 1024; i++)
buf1.data()[i] = (char) (i % 256);
socketClient->Write(&len, 1);
socketClient->Write(buf1, len * 1024);
wxPrintf("End!\n");
while (1) {
}
return 0;
}
Server
#include <wx/wxprec.h>
#include <wx/cmdline.h>
#include <wx/socket.h>
#include <wx/app.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
static const wxCmdLineEntryDesc cmdLineDesc[] = {
{ wxCMD_LINE_SWITCH, "h", "help", "show this help message",
wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP},
{ wxCMD_LINE_SWITCH, "d", "dummy", "a dummy switch"},
// ... your other command line options here...
{ wxCMD_LINE_NONE}
};
int main(int argc, char **argv) {
// Startup
wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "program");
wxInitializer initializer;
if (!initializer) {
fprintf(stderr, "Failed to initialize the wxWidgets library, aborting.\n");
return -1;
}
// Creat socket
wxPrintf("Criando socket...\n");
wxSocketServer *socketServer;
wxIPV4address addr;
if (!addr.Hostname("127.0.0.1")) {
wxPrintf("Could not set hostname !\n");
return 1;
}
if (!addr.Service(3000)) {
wxPrintf("Could not set service !\n");
return 1;
}
socketServer = new wxSocketServer(addr);
if (!socketServer->IsOk()) {
wxPrintf("Could not listen at the specified port !\n");
return 1;
}
// Efetuar conexao
wxPrintf("Waiting for connection...\n");
socketServer->Accept(1);
if (socketServer->IsConnected()) {
wxPrintf("Success\n");
} else {
wxPrintf("Not connected\n");
}
while (1) {
}
return 0;
}
After hours studying and trying, I solved the problem.
wxPrintf("Waiting for connection...\n");
wxSocketBase socketTest;
socketServer->AcceptWith(socketTest, true);
if (socketTest.IsConnected()) {
wxPrintf("Success\n");
} else {
wxPrintf("Not connected\n");
}
In the manual is written a detail that had not understood:
Accepts an incoming connection request, and creates a new wxSocketBase
object which represents the server-side of the connection.

Sending data to multiple clients connected on my Server

I have this server app where clients can connect to. Now i want that when the clients are connected i can send data to all of them. I manage to do it when i connect my two clients.. what i send is received by my two clients. but my problem is when i connect client1 then send data to server, client1 can receive data then i connect client2 and i send data to the server. now when i send data from server to my clients only client1 can receive data but when i disconnect client 1 then client2 can receive data from the server.
How can i make them work at the same time?.. Also how can i make my server accept messages at the same time from my client?..
Here's the part of the code im having trouble.
for(j=0;j<MAX_CLIENTS; j++)
Clients[j].connected_sock = -1;
do
{
fduse = fdin;
printf("Waiting for Connection\n");
err = select(sMax + 1, &fduse, NULL, NULL, NULL);
if (err < 0)
{
perror(" select() failed");
break;
}
DescRead = err;
for (SockStorage=0; SockStorage <= sMax && DescRead > 0; ++SockStorage)
{
if (FD_ISSET(SockStorage, &fduse))
{
DescRead -= 1;
if (SockStorage == socketFd)
{
printf(" Listening socket is readable\n");
do
{
NewSFD = accept(socketFd,(struct sockaddr *) &cli_addr, &clilen);
if (NewSFD < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" accept() failed");
DCSERVER = TRUE;
}
break;
}
if(ClientCount < MAX_CLIENTS){
for(loop = 0; loop <MAX_CLIENTS; loop++){
if(Clients[loop].connected_sock<0){
Clients[loop].connected_sock = NewSFD;
break;
}
}
ClientCount++;
}
else
{
printf("Maximum Client Reached.\n");
char *sendtoclient = "Server full. ";
send(NewSFD, sendtoclient, strlen(sendtoclient),0);
close(NewSFD);
break;
}
ip = ntohl(cli_addr.sin_addr.s_addr);
printf(" Connection from %d.%d.%d.%d\n",
(int)(ip>>24)&0xff,
(int)(ip>>16)&0xff,
(int)(ip>>8)&0xff,
(int)(ip>>0)&0xff);
dlogs(ip);
FD_SET(NewSFD, &fdin);
if (NewSFD > sMax)
sMax = NewSFD;
} while (NewSFD != -1);
}
else
{
int d;
for(d=0; d<MAX_CLIENTS; d++){
printf("Descriptor ID: %d\n", Clients[d].connected_sock);
}
pfds[0].fd = fd;
pfds[0].events = POLLIN;
pfds[1].fd = SockStorage;
pfds[1].events = POLLIN;
state = FALSE;
do
{
rc = poll(pfds, 2, -1);
if (pfds[0].revents & POLLIN)
{
while ((nbytes = read(fd, buf, sizeof(buf)-1)) > 0)
{
buf[nbytes] = '\0';
printf("%s\n", buf);
}
pfds[0].events = 0;
pfds[1].events = POLLIN | POLLOUT;
}
if (pfds[1].revents & POLLIN)
{
err = recv(SockStorage, strbuf, sizeof(strbuf), 0);
if (err < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" recv() failed");
state = TRUE;
}
break;
}
if (err == 0)
{
printf(" Connection closed\n");
state = TRUE;
break;
}
dSize = err;
printf(" %d bytes received\n", dSize);
}
if (pfds[1].revents & POLLOUT)
{
int s;
for(s=0; s<MAX_CLIENTS; s++){
if(Clients[s].connected_sock>0){
err = send(Clients[s].connected_sock, buf, strlen(buf), 0);
if (err < 0)
{
perror(" send() failed");
state = TRUE;
break;
}
}
}
pfds[0].events = POLLIN;
pfds[1].events = POLLIN;
}
} while (TRUE);
Here's how im sending data to my clients.
int s;
for(s=0; s<MAX_CLIENTS; s++){
if(Clients[s].connected_sock>0){
err = send(Clients[s].connected_sock, buf, strlen(buf), 0);
if (err < 0)
{
perror(" send() failed");
state = TRUE;
break;
}
}
}
Thanks,
There are generally couple of possible solutions:
You can use separate threads for each client connection;
You can use select;
You can use poll;
You can use epoll;
In Windows environment there are also some other possibilities like IOCP for example.
Each of mentioned solutions have some pros and cons (you need generally distinguish between simplicity and performance).
You can read some network programming tutorial for more details, e.g. this.

Resources