I am trying to let my c++ program communicate with simulink model via udp, and in particularly the plan is that data will be transmitted from c++ to simulink, and will be processed using some simulink models, then the result will be sent back to c++ for further programming, and data trasmissions will be realized through udp, (udp socket for c++, and udp real time send/receive block for simulink). And it will repeat a few times.
I've built a while loop, where c++ keeps reading data from a txt file and sends it to simulink via udp, which works well, the data has been multiplied by 2 and sent back towards c++, but c++ cannot receive correct data as was sent from simulink. The data it received during each cycle is "0". But if the data I sent was a constant, the receiving function in c++ works fine as well.
ifstream file_x("x1.txt");
ifstream file_y("y1.txt");
ifstream file_z("z1.txt");
double x;
double y;
double z;
int main()
{
//Local Varaiable definition
cout<<"\t\t--------------------UDP Server----------------"<<endl;
cout<<endl;
WSADATA WinsockData;
int iWsaStartup;
int iWsaCleanup;
SOCKET UDPSocketServer1;
SOCKET UDPSocketClient3;
struct sockaddr_in UDPClient1;
struct sockaddr_in UDPServer3;
char Buffer1[200];
char Buffer3[200];
int iBufferLen1 = 200+1;
int iBufferLen3 = 200+1;
int iBind3;
int iReceiveFrom;
int iSendTo;
int iUDPClientLen1 = sizeof(UDPClient1);
int iUDPClientLen2 = sizeof(UDPClient2);
int iUDPServerLen3 = sizeof(UDPServer3);
int iCloseSocket1;
int iCloseSocket3;
//STEP-1: initialization of Winsock
iWsaStartup = WSAStartup(MAKEWORD(2,2), &WinsockData);
if (iWsaStartup != 0)
{
cout<<"WSAStartUp Fun Failed!"<<endl;
}
else
{
cout<<"WSAStartUp Success"<<endl;
}
//STEP-2: Fill the UDPClient(SOCKET ADDRESS) Structure
UDPClient1.sin_family = AF_INET;
UDPClient1.sin_addr.s_addr = inet_addr("127.0.0.1");
UDPClient1.sin_port = htons(8001);
UDPServer3.sin_family = AF_INET;
UDPServer3.sin_addr.s_addr = inet_addr("127.0.0.3");
UDPServer3.sin_port = htons(8003);
//STEP-3: Socket Creation
UDPSocketServer1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (UDPSocketServer1 == INVALID_SOCKET)
{
cout<<"Socket1 Creation Failed & Error No ->"<<WSAGetLastError()<<endl;
}
else
{
cout<<"Socket1 Creation Success"<<endl;
}
UDPSocketClient3 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (UDPSocketClient3 == INVALID_SOCKET)
{
cout<<"Socket3 reation Failed = "<<WSAGetLastError()<<endl;
}
else
{
cout<<"Socket3 Creation Success"<<endl;
}
//STEP-4: Bind the server
iBind3 = bind(UDPSocketClient3, (SOCKADDR*)&UDPServer3, sizeof(UDPServer3));
if (iBind3 == SOCKET_ERROR)
{
cout<<"Binding Failed & Error No ->"<<WSAGetLastError()<<endl;
}
//STEP-4-1: SendTo Fun send data to client
while (!file_x.eof())
{
file_x >> x;
file_y >> y;
file_z >> z;
sprintf_s(Buffer1,200,"%0.2f\r\n %0.2f\r\n %0.2f\r\n",x,y,z);
iSendTo = sendto(UDPSocketServer1, Buffer1, iBufferLen1, MSG_DONTROUTE, (SOCKADDR*)&UDPClient1, sizeof(UDPClient1));
if (iSendTo == SOCKET_ERROR)
{
cout<<"Sending Data Failed & Error No ->"<<WSAGetLastError()<<endl;
}
else
{
cout<<"Sending Data Success"<<endl;
}
iReceiveFrom = recvfrom(UDPSocketClient3, Buffer3, iBufferLen3, MSG_PEEK, (SOCKADDR*)&UDPServer3, &iUDPServerLen3);
if (iReceiveFrom == SOCKET_ERROR)
{
cout<<"Receiving failed & Error No ->"<<WSAGetLastError()<<endl;
}
else
{
cout<<"Receiving Success"<<endl;
cout<<"Receive Data ->"<<Buffer3<<endl;
}
}
//STEP-6: CloseSocket Function
iCloseSocket1 = closesocket(UDPSocketServer1);
if (iCloseSocket1 == SOCKET_ERROR)
{
cout<<"Socket1 Closing failed & Error No ->"<<WSAGetLastError()<<endl;
}
else
{
cout<<"Socket1 Closing Success"<<endl;
}
iCloseSocket3 = closesocket(UDPSocketClient3);
if (iCloseSocket3 == SOCKET_ERROR)
{
cout<<"Socket3 Closing failed & Error No ->"<<WSAGetLastError()<<endl;
}
else
{
cout<<"Socket3 Closing Success"<<endl;
}
//STEP-7: WSACleanUp Fun for Terminating from DLL
iWsaCleanup = WSACleanup();
if (iWsaCleanup == SOCKET_ERROR)
{
cout<<"WSA Cleanup Success"<<endl;
}
else
{
cout<<"WSA Cleanup Success"<<endl;
}
system("pause");
return 0;
}
I found that flag in recvfrom function matters in this issue, which can be referred to its document and I've changed MSG_PEEK to 0 and considering my application, I've used another project for only receiving data sent from simulink, and the issue has been solved.
Related
I want to send random trigger signals (A and B) from Matlab to a C++ Code. The point where I stuck now is, that whenever I am not sending this trigger signal/message, the C++ Code keeps waiting for it and doesn't continue its process.
How can I make the C++ Code keep running (to collect data) without waiting for the next trigger message. Because now only once it receives the message (UDP transfers trigger signal) it gives me the specific outcome.
----------- BEGIN MATLAB CODE ---------------------
send_trigger_signal = instrfind('Type', 'udp', 'LocalHost', '127.0.0.1','RemoteHost', '192.168.0.100', 'RemotePort', 8888, 'LocalPort', 8844, 'Tag', '');
% Create the udp object if it does not exist otherwise use the object that was found.
if isempty(send_trigger_signal)
send_trigger_signal = udp('127.0.0.1', 'RemotePort', 8888, 'LocalPort', 8844);
else
fclose(send_trigger_signal);
send_trigger_signal = send_trigger_signal(1);
end
send_trigger_signal.DatagramTerminateMode='off';
send_trigger_signal.Timeout=0.0001;
send_trigger_signal.Timerperiod=0.01;
%send_trigger_signal.
% Connect to instrument object, send_trigger_signal.
fopen(send_trigger_signal);
% Communicating with instrument object, send_trigger_signal.
on_trigger_command=typecast(swapbytes(uint16([1 1 0 0])),'uint8'); %trigger on
off_trigger_command=typecast(swapbytes(uint16([0 0 0 0])),'uint8'); %trigger off
while(true)
for i=1:1
fprintf(send_trigger_signal, 'A');
WaitSecs(5);
end
end
fclose(send_trigger_signal);
send_trigger_signal=instrfindall;
delete(send_trigger_signal);
instrfindall;
----------- END MATLAB CODE ---------------------
This is the C++ code which should receive the random trigger signals from Matlab (A and B), while collecting gyro data between those signals.
To test it here the message is send every 5sec. The problem is that I cannot collect the gyro data in within those 5sec. The UDP communication is interrupting the data collection - because it is waiting those 5sec.
----------- START C++ CODE ---------------------
#include <iostream>
#include <winsock2.h>
using namespace std;
#pragma comment(lib,"ws2_32.lib") // Winsock Library
#pragma warning(disable:4996)
#define BUFLEN 512
#define PORT 8888
int receiver(void)
{
int value = 5;
system("title UDP Server");
sockaddr_in server, client;
// initialise winsock
WSADATA wsa;
printf("Initialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code: %d", WSAGetLastError());
exit(0);
}
printf("Initialised.\n");
// create a socket
SOCKET server_socket;
if ((server_socket = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
printf("Could not create socket: %d", WSAGetLastError());
}
printf("Socket created.\n");
// prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
// bind
if (bind(server_socket, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code: %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done.");
while (true)
{
printf("Waiting for data...");
fflush(stdout);
char message[BUFLEN] = {};
// try to receive some data, this is a blocking call
int message_len;
int slen = sizeof(sockaddr_in);
if (message_len = recvfrom(server_socket, message, BUFLEN, 0, (sockaddr*)&client, &slen) == SOCKET_ERROR)
{
printf(message);
printf("recvfrom() failed with error code: %d", WSAGetLastError());
exit(0);
}
if (message[0] == 'A')
{
value = 6;
break;
}
if (message[0] == 'B')
{
value = 7;
break;
}
// print details of the client/peer and the data received
printf("Received packet from %s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
printf("Data: %s\n", message);
return 0;
}
closesocket(server_socket);
WSACleanup();
return value;
}
int main()
{
while (true)
{
// Reading some gyro data here
// Listening UDP
receiver();
}
return 0;
}
----------- END C++ CODE ---------------------
With a few structural tweaks:
Using non-blocking socket.
You don't want to restart winsock and rebind the socket every time you read from it, so that's spun off to different functions (an RAII wrapper class in the case of winsock).
C-style IO replaced with C++ IO.
exit(0) means the program succeeded, but was used in many cases where failure occurred. Consistently using exit(EXIT_FAILURE);. Might be worth throwing an exception, but it's annoying to get the error code into the exception text.
Removed some of the output because it would be spammed out now that the receive function can immediately return .
Your program could look something like this:
#include <iostream>
#include <winsock2.h>
using namespace std;
#pragma comment(lib,"ws2_32.lib") // Winsock Library
#pragma warning(disable:4996)
// using modern C++ constants
constexpr int BUFLEN = 512;
constexpr int PORT = 8888;
//RAII wrapper to make sure winsock is created and disposed of responsibly
struct winsock_RAII
{
winsock_RAII()
{
WSADATA wsa;
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
std::cerr << "Failed to initialize winsock. Error Code: " << WSAGetLastError() << '\n';
exit(EXIT_FAILURE);
}
}
~winsock_RAII()
{
WSACleanup(); // what are we gonna do if it fails? Not much we can do.
}
};
//socket initialization
SOCKET init_sock()
{
SOCKET server_socket;
if ((server_socket = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
std::cerr << "Failed to get socket. Error Code: " << WSAGetLastError() << '\n';
exit(EXIT_FAILURE);
}
u_long iMode = 1;
//setr socket non-blocking
if (ioctlsocket(server_socket, FIONBIO, &iMode) != NO_ERROR)
{
std::cerr << "Failed to get socket. Error Code: " << WSAGetLastError() << '\n';
exit(EXIT_FAILURE);
}
// prepare the sockaddr_in structure
sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
// bind
if (bind(server_socket, (sockaddr*) &server, sizeof(server)) == SOCKET_ERROR)
{
std::cerr << "Bind failed. Error Code: " << WSAGetLastError() << '\n';
exit(EXIT_FAILURE);
}
return server_socket;
}
// read from socket
int receiver(SOCKET server_socket)
{
// try to receive some data, this is a non-blocking call
int slen = sizeof(sockaddr_in);
sockaddr_in client;
char message[BUFLEN + 1]; // no need to clear the whole buffer. We'll know
// exactly where to put the null thanks to message_len
// +1 makes sure we have room for terminator
int message_len = recvfrom(server_socket, message,
BUFLEN,
0,
(sockaddr*) &client,
&slen);
int value = 5;
if (message_len != SOCKET_ERROR)
{
message[message_len] = '\0'; // place terrminator
if (message[0] == 'A')
{
value = 6;
}
if (message[0] == 'B')
{
value = 7;
}
// print details of the client/peer and the data received
std::cout << "Received packet from " << inet_ntoa(client.sin_addr) << ':' << ntohs(client.sin_port) << '\n'
<< "Data: " << message << '\n';
}
else if (WSAGetLastError() != WSAEWOULDBLOCK)
{
// printf(message); no point to printing message. There isn't one
std::cerr << "recvfrom() failed . Error Code: " << WSAGetLastError() << '\n';
exit(EXIT_FAILURE);
}
return value;
}
int main()
{
winsock_RAII winsock; // scoped winsock initializer
SOCKET server_socket = init_sock();
while (true)
{
// Reading some gyro data here
receiver(server_socket);
}
closesocket(server_socket);
return 0;
}
You might want to use select with a short timeout to throttle the loop because it can be a serious and unnecessary CPU-eater if the gyro reading code is also quick.
What I'm trying to do is a forking proxy that deals HTTP(S) connections: while GET (without SSL) requests are successfully executed and the contents are delivered to the client, when it comes to CONNECT method things are not going well, since connect()ing to the remote server may not immediately succeeds: in fact, it nevers succeeds.
I tried for a non blocking socket connected to the remote server, so I can see if connect() goes immediately or takes some time: in the second case, I'd call select() to see when the remote server is ready to send data to me: yet, connect() never connects.
Here's my proxy main() code:
int main(int argc, char *argv[]) {
// ClientManager.cpp is described below
ClientManager cm;
//listening on port given by argv
if (cm.startListeningForClient(listening_port)) {
while(true) {
int new_client_socket = cm.acceptConnectionFromClient();
if (new_client_socket >= 0) {
cm.forkAndManageClient();
}
else {
perror("accept error");
}
}
} else {
perror("Error on start listening");
}
return EXIT_SUCCESS;
}
Now follows, with some omissis not involved with my issue, ClientManager.cpp, whose functions are called in main() above:
ClientManager::ClientManager() {
sockfd_client = -1; // socket connected to client
new_sockfd_client = -1; // socket accepting connection from client
sockfd_server = -1; // socket connected to remote server
}
// error controls omitted
bool ClientManager::startListeningForClient(int port) {
struct sockaddr_in serv_addr;
bzero((char*)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(port);
serv_addr.sin_addr.s_addr=INADDR_ANY;
sockfd_client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
bind(sockfd_client,(struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(sockfd_client, 50);
return true;
}
// error controls omitted
int ClientManager::acceptConnectionFromClient(void) {
struct sockaddr_in cli_addr;
unsigned int clilen;
bzero((char*)&cli_addr, sizeof(cli_addr));
clilen = sizeof(cli_addr);
new_sockfd_client = accept(sockfd_client, (struct sockaddr*)&cli_addr, &clilen);
return new_sockfd_client;
}
int ClientManager::forkAndManageClient() {
// getRequestFromClient: the method below receives requests from
// clients and parses the infos I need (i.e. what method,
// hostname of remote server to be resolved, its port, ...)
getRequestFromClient();
// managing the HTTP(S) request by the child process
int pid = fork();
if (pid < 0) {
perror("ERROR on fork");
}
else if (pid > 0) {
// parent process
// do nothing
}
else {
// close immediately the client socket used for accepting new connections from the parent process
close (sockfd_client);
if (!manageRequest()) {
perror("Error managing request from client");
}
// close the connection from the client
close (new_sockfd_client);
new_sockfd_client = -1;
// the child process will terminate now
_exit(EXIT_SUCCESS);
}
return pid;
}
// now the problematic method...
bool ClientManager::manageRequest(void) {
// if this is a CONNECT request
if (rm.isCONNECT()) {
struct sockaddr_in remote_server;
int conn_res;
remote_server.sin_family = AF_INET;
remote_server.sin_addr.s_addr = rm.getServerAddr();
remote_server.sin_port = rm.getServerPort();
fd_set fdset;
struct timeval tv;
sockfd_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// make socket not blocking
int flags = fcntl(sockfd_server, F_GETFL, 0);
flags = flags | O_NONBLOCK;
if (fcntl(sockfd_server, F_SETFL, flags) == -1) {
perror("FCNTL:");
}
printf("CONNECT set socket to non-blocking mode\n");
conn_res = connect(sockfd_server, (struct sockaddr *)&remote_server, sizeof(struct sockaddr_in));
printf("AFTER CONNECT()\n");
if (conn_res < 0) {
if (errno != EINPROGRESS) {
printf("CONNECT: connect() failed, quitting\n");
return false;
}
}
printf("CONNECT connection is taking place...\n");
// connected immediately
if (conn_res == 0) {
printf("CONNECT connected OK!\n");
goto CONNECTED;
}
FD_ZERO(&fdset);
FD_SET(sockfd_server, &fdset);
tv.tv_sec = 5; // tried 5, 20, 60 seconds, but it always times out
tv.tv_usec = 0;
printf("CONNECT attempting select()\n");
if (select(sockfd_server+1, NULL, &fdset, NULL, &tv) == 0) {
errno = ETIMEDOUT;
close(sockfd_server);
sockfd_server = -1;
return false;
}
if (FD_ISSET(sockfd_server, &fdset)) {
int so_error;
socklen_t len = sizeof so_error;
if (getsockopt(sockfd_server, SOL_SOCKET, SO_ERROR, &so_error, &len) < 0) {
return false;
}
} else {
printf("sockfd_server not set\n");
}
CONNECTED:
fcntl(sockfd_server, F_SETFL, flags &~ O_NONBLOCK);
// yeah, now I will start to deal the HTTPS flow in both directions
return true;
}
}
It does manage setting socket to non blocking mode, and to print CONNECT connection is taking place..., but it always returns Error managing request from client: Connection timed out.
I apologize for posting miles of LOC, but this is what drives me crazy since days, and after reading posts, tutorial and guides, I really don't know what to do.
It connects now to every site which requires an HTTPS connection!
Proper error checking and following closing of socket descriptors were missing. Here's my code:
bool ClientManager::manageRequest(void) {
if (rm.isCONNECT()) {
struct sockaddr_in remote_server, local_bind;
int conn_res, select_res;
memset(&remote_server, 0, sizeof(remote_server));
remote_server.sin_family = AF_INET;
remote_server.sin_addr.s_addr = rm.getServerAddr();
remote_server.sin_port = rm.getServerPort();
memset(&local_bind, 0, sizeof(local_bind));
local_bind.sin_family = AF_INET;
local_bind.sin_addr.s_addr = htonl(INADDR_ANY);
local_bind.sin_port = htons(0);
fd_set rdset, wrset;
struct timeval tv;
sockfd_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd_server < 0) {
perror("socket: ");
}
if(!setNonBlocking(sockfd_server))
perror("fcntl");
debug_green("CONNECT set socket to non-blocking mode\n");
bind(sockfd_server, (struct sockaddr*) &local_bind, sizeof(local_bind));
conn_res = connect(sockfd_server, (struct sockaddr *)&remote_server, sizeof(struct sockaddr_in));
// The socket is nonblocking and the connection cannot be completed immediately
// check for EINPROGRESS
if ((conn_res == -1) && (errno != EINPROGRESS)) {
FD_ZERO(&rdset);
FD_SET(sockfd_server, &rdset);
wrset = rdset;
tv.tv_sec = 0;
tv.tv_usec = 0;
debug_yellow("CONNECT attempting select()\n");
do {
select_res = select(sockfd_server+1, &rdset, &wrset, NULL, &tv);
} while ((select_res == -1) && (errno == EINTR));
if ((!FD_ISSET(sockfd_server, &rdset)) && ((!FD_ISSET(sockfd_server, &wrset)))) {
debug_red("SELECT sockfds not responding\n");
close(sockfd_server);
sockfd_server = -1;
return false;
}
conn_res = connect(sockfd_server, (struct sockaddr *)&remote_server, sizeof(struct sockaddr_in));
if (conn_res == -1) {
if(errno == EISCONN)
printf ("connect(): connections already existing, OK\n");
else {
printf("connect() for safety check: connection NOT successfull\n");
close(sockfd_server);
sockfd_server = -1;
return false;
}
}
printf("connection OK\n");
fflush(stdout);
} else {
debug_green("Connection immediately OK\n");
fflush(stdout);
}
if (!setBlocking(sockfd_server)) {
perror("FCNTL:");
}
debug_green("CONNECT set socket back to blocking mode\n");fflush(stdout);
}
return true;
}
Functions setting blocking or non blocking socket:
bool ClientManager::setNonBlocking(int sockfd) {
printf("setting non block socket\n"); fflush(stdout);
int flags;
if ((flags = fcntl(sockfd, F_GETFL, 0)) < 0)
return false;
flags |= O_NONBLOCK;
if (fcntl(sockfd, F_SETFL, flags) < 0)
return false;
return true;
}
bool ClientManager::setBlocking(int sockfd) {
printf("setting block socket\n"); fflush(stdout);
int flags;
if ((flags = fcntl(sockfd, F_GETFL, 0)) < 0)
return false;
flags &= (~O_NONBLOCK);
if (fcntl(sockfd, F_SETFL, flags) < 0)
return false;
return true;
}
Debug functions:
#define DEFAULTCOLOR "\033[0m"
#define RED "\033[22;31m"
#define YELLOW "\033[1;33m"
#define GREEN "\033[0;0;32m"
#define debug_red(...) std::cout << RED << __VA_ARGS__ << DEFAULTCOLOR; fflush(stdout);
#define debug_yellow(...) std::cout << YELLOW << __VA_ARGS__ << DEFAULTCOLOR; fflush(stdout);
#define debug_green(...) std::cout << GREEN << __VA_ARGS__ << DEFAULTCOLOR; fflush(stdout);
I have a TCP application written in C++, where a client and a server exchange data. I've istantiated a socket, believing that it would have been blocking by default; on the contrary, after server waits for a client, I have that client calls the recv function without waiting for data. This is the code in which I inizialize the socket fr the client.
int TCPreceiver::initialize(char* address, int port)
{
sock = socket (AF_INET, SOCK_STREAM, 0);
cout << "Socket: " << sock << endl;
sockaddr_in target;
target.sin_family = AF_INET;
target.sin_port = htons (port);
target.sin_addr.s_addr = inet_addr(address);
int fails=0;
while (connect(sock, (sockaddr*) &target, sizeof(target)) == -1)
{
fails++;
if (fails==10)
{
close(sock);
cout << "Error with connection to the server, try again"<< endl;
exit(-1);
}
}
cout << "Client connected (control channel)" << endl;
unsigned char text[10]; //Request message
//fill text[]
if(send(sock, (char*)text, 10, 0)==-1)
{
printf("send() failed with error code : %d" , -1);
exit(EXIT_FAILURE);
}
return 0;
}
I've tried adding this code:
int opts;
opts = fcntl(sock,F_GETFL);
if (opts < 0) {
perror("fcntl(F_GETFL)");
exit(0);
}
opts = (opts & (~O_NONBLOCK));
if (fcntl(sock,F_SETFL,opts) < 0) {
perror("fcntl(F_SETFL)");
exit(0);
}
but it still doesn't work, and if I call the recv(), the application doesn't block (and recv() always returns 0). Here is the function where I call the recv():
void TCPreceiver::receive(char* text, int& dim)
{
int ret;
ret = recv(sock, text, dim, 0);
dim=ret;
if(ret == -1){
printf("recv() failed with error (%d)\n", ret);
//system("PAUSE");
exit(1);
}
}
Where am I wrong?
recv() returning zero indicates either (1) you passed a zero length, which is just a programming error which I won't discuss further here, or (2) end of stream. The peer has close the connection. This isn't a non-blocking situation, this is the end of the connection. You must close the socket and stop using it. It will never return anything. It zero ever again.
See the man pages.
I am working on a client-server application where I have two different ports, one (principal) for us send and receive messages or any other order, and another one to send and receive screenshots of the server to the client. From client to server notice to start us send'll catch and showing in a new window ... works fine but if I close the window and open it again then and I can not connect to that port (bind fails me).
MY question is how do I clean or completely release the port I use for screenshots without affecting the main port, that is, when you close the window to release the port as if I had never used and advise the client to do the same.
Here I leave the code:
Server:
int serviceCapture(int port)
{
int error;
WSAData wsaDataER;
error = WSAStartup(MAKEWORD(2, 2), &wsaDataER);
if (error == SOCKET_ERROR)
{
return 1;
}
// ShowMessage ("Server: WinSocket Started Correctly!\n");
sock_ER = socket(AF_INET, SOCK_STREAM, 0);
if (sock_ER == SOCKET_ERROR)
{
return 2;
}
struct sockaddr_in escritorioRem; // New! Our network socket structure
escritorioRem.sin_family = AF_INET; // Always have ti as this for internet
escritorioRem.sin_port = htons(puerto); // Dont forget the byte ordering
escritorioRem.sin_addr.s_addr = INADDR_ANY;internet
if(!enviandoCapturas){
error = bind(sock_ER, (sockaddr*)&escritorioRem, sizeof(escritorioRem)); // Attempt to bind the socket
if (error == SOCKET_ERROR)
{
return 3 ;
}
}
error = listen(sock_ER, 1); // Listen for connections
if (error == SOCKET_ERROR)
{
return 4;
}
// }
//ShowMessage ( "Server: Waiting for a client to connect ...\n"); // Just to keep us up to date - ish
int len= sizeof (struct sockaddr);
sock_ER=accept(sock_ER,(sockaddr*)&escritorioRem, &len);
//
//do{
if( sock_ER<0){
return 5;
}
sendingCaps=true;
startSendCaps();
return 0;
}
Client:
int client(string serv, int puerto)
{
int error;
WSAData wsaData;
error = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (error == SOCKET_ERROR)
{
return 1;
}
// ShowMessage( "Client: WinSocket Loaded.\n");
if (sock == SOCKET_ERROR)
{
return 2;
}
// ShowMessage( "Client: Socket Opened Successfully!\n");
const char *server_name = serv.c_str(); // The server name we will connect to
struct hostent *host_entry; // Translates into something the computer can understand
host_entry = gethostbyname(server_name); // Gather out information
if (host_entry == NULL)
{
return 3;
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons((unsigned short) puerto);
server.sin_addr.s_addr = *(unsigned long*) host_entry->h_addr;
if(connect(ventanaCliente->sock, (sockaddr*)&server, sizeof(struct sockaddr))<0){
return 4;
}
receivingCaps=true;
strartReceiveCaps();
return 0;
}
back again (sorry)
I've created a socket C++ application, but it isn't working properly.
This is my first code:
void Network::Start()
{
this->socket = Env::GetSocket();
SOCKADDR_IN sInformation;
sInformation.sin_family = AF_INET;
sInformation.sin_addr.s_addr = INADDR_ANY;
sInformation.sin_port = htons(30000);
bind(this->socket, (SOCKADDR*) (&sInformation), sizeof(sInformation));
listen(this->socket, 10);
while (true)
{
this->DO();
}
}
And the DO function:
void Network::DO()
{
SOCKET s = SOCKET_ERROR;
sockaddr_in sock_addr;
accept(s, (sockaddr*) &sock_addr, NULL);
if (INVALID_SOCKET == s)
{
return;
}
else
{
cout << "Received connection from " << inet_ntoa(sock_addr.sin_addr);
}
}
What happens, always (even if I connect) the value s is INVALID_SOCKET. I connect via a .SWF but it doesn't accept my connection. What am I doing wrong?
You are not doing adequate error handling, and you are not using accept() correctly. Try this:
void Network::Start()
{
this->socket = Env::GetSocket();
if (this->socket == INVALID_SOCKET)
{
// error
return;
}
SOCKADDR_IN sInformation = {0};
sInformation.sin_family = AF_INET;
sInformation.sin_addr.s_addr = INADDR_ANY;
sInformation.sin_port = htons(30000);
if (bind(this->socket, (SOCKADDR*) &sInformation, sizeof(sInformation)) != 0)
{
// error
return;
}
if (listen(this->socket, 10) != 0)
{
// error
return;
}
while (true)
{
this->DO();
}
}
void Network::DO()
{
SOCKADDR_IN sock_addr = {0};
socklen_t sock_addr_len = sizeof(sock_addr);
SOCKET s = accept(this->socket, (SOCKADDR*) &sock_addr, &sock_addr_len);
if (INVALID_SOCKET == s)
{
return;
}
cout << "Received connection from " << inet_ntoa(sock_addr.sin_addr);
// use s as needed. Don't forget to call close(s) or closesocket(s)
// when finished, depending on your platform...
}
accept takes the listening socket as a parameter, and returns the newly connected socket;
socklen_t length = sizeof(sockaddr_in);
s = accept(this->socket, (sockaddr*) &sock_addr, &length);
EDIT: Just tested the program, with the socket created with AF_INET, SOCK_STREAM and sInformation cleared out;
bzero((char *) &sInformation, sizeof(sInformation));
...it seems to be running well on MacOS X and linux.