Winsock Bluetooth subsequent calls to send function fails with WSAECONNABORTED - c++

I am trying to create simple windows bluetooth client application. However after successfull connect the send() function is sending data only for a short duration. The subsequent calls to send() function fail with code: 10053 (WSAECONNABORTED).
From docs:
Software caused connection abort. An established connection was aborted by the software in your host computer, possibly due to a data transmission time-out or protocol error.
If I understand it correctly the error is occuring on Windows (client) side and not on the server side?
What could be causing it?
Also is it possible to somehow reconnect this socket?
The code (simplified, missing error checks):
#include <winsock2.h>
#include <ws2bth.h>
#include <iostream>
// {B62C4E8D-62CC-404b-BBBF-BF3E3BBB1374} ]taken from Microsoft example
DEFINE_GUID(gGuidServiceClass, 0xb62c4e8d, 0x62cc, 0x404b, 0xbb, 0xbf, 0xbf, 0x3e, 0x3b, 0xbb, 0x13, 0x74);
unsigned char dummyData [10] =
{
0x01, 0x02, 0x03, 0x04, 0x05,
0x01, 0x02, 0x03, 0x04, 0x05
};
int main(void)
{
WSAData wsaData = {0};
SOCKADDR_BTH btAddr = {0};
uint32_t flags = 0;
WSAStartup(MAKEWORD(2, 2), &wsaData);
btAddr.addressFamily = AF_BTH;
btAddr.serviceClassId = gGuidServiceClass;
btAddr.port = 0;
btAddr.btAddr = // hardcoded address here
SOCKET s = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if (SOCKET_ERROR == connect(s, (struct sockaddr *) &btAddr, sizeof(SOCKADDR_BTH)))
{
std::cout << "socket connect fail: " << WSAGetLastError() << std::endl;
return -1;
}
int32_t bytes = send(s, reinterpret_cast<char *>(dummyData), 10, 0);
if (bytes == 10)
{
std::cout << "first send success\n";
}
// success
// do some processing
// repeat
bytes = send(s, reinterpret_cast<char *>(dummyData), 10, 0);
if (bytes < 0)
{
// always fail with 10053
std::cout << "Error: " << WSAGetLastError() << std::endl;
}
closesocket(s);
WSACleanup();
return 0;
}

Related

UDP signal from Matlab to C++

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.

Linux UDP ephemeral port bind occasionally fails to receive

I am writing a set of tests that depend on two applications communicating (locally) with a UDP socket. These UDP sockets are originally bound using port 0, then the actual bound port is queried using getsockname and shared between the two applications. Occasionally, the subsequent recv calls fail to return any data without any error reporting during binding etc.
I've simplified my implementation to a bare-bones test an included it below. It fails with "Received failed, got -1 expeccted 6" about 1 of 10 runs. What am I missing in the socket setup to reliable use an ephemeral, OS-assigned port?
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include <thread>
int32_t createSocket(uint16_t& rBoundPort)
{
int32_t s = socket(AF_INET, SOCK_DGRAM, 0);
if (s >= 0)
{
timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeval)) < 0)
{
::close(s);
return -1;
}
int32_t r(1);
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &r, sizeof(int)) < 0)
{
close(s);
return -1;
}
int32_t bufSize(50000);
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &bufSize, sizeof(bufSize)) < 0)
{
close(s);
return -1;
}
// Setup local listening port
sockaddr_in listenAddress;
memset(reinterpret_cast<char*>(&listenAddress), 0, sizeof(listenAddress));
listenAddress.sin_family = AF_INET;
inet_aton("127.0.0.1", &listenAddress.sin_addr);
listenAddress.sin_port = htons(0);
if (bind(s, (struct sockaddr*)&listenAddress, sizeof(listenAddress)) != 0)
{
close(s);
return -1;
}
// Update the bound listen port
socklen_t boundAddrLen = sizeof(sockaddr_in);
getsockname(s, (struct sockaddr*)&listenAddress, &boundAddrLen);
rBoundPort = ntohs(listenAddress.sin_port);
}
return s;
}
void mysockettest(int32_t s, uint16_t destPort)
{
const int32_t dataSize = 6;
char aWrite[dataSize] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
char aRx[dataSize];
sockaddr_in dest;
memset((char*)&dest, 0, sizeof(dest));
dest.sin_family = AF_INET;
inet_aton("127.0.0.1", &dest.sin_addr);
dest.sin_port = htons(destPort);
sendto(s, aWrite, dataSize, 0, (struct sockaddr*)&dest, sizeof(sockaddr_in));
sockaddr_in src;
socklen_t srcSize = sizeof(sockaddr_in);
memset((char*)&src, 0, srcSize);
int32_t bytesReceived = recvfrom(s, aRx, dataSize, 0, (struct sockaddr*)&src, &srcSize);
if (bytesReceived != dataSize)
{
printf("Received failed, got %d expected %d\n", bytesReceived, dataSize);
}
}
int main(int argc, char** pargv)
{
uint16_t s1Port(0);
int32_t s1 = createSocket(s1Port);
if (s1 < 0)
{
printf("FAILED TO OPEN SOCKET 1\n");
return -1;
}
if (s1Port < 1)
{
printf("FAILED TO BIND SOCKET 1 TO PORT\n");
return -1;
}
uint16_t s2Port(0);
int32_t s2 = createSocket(s2Port);
if (s2 < 0)
{
printf("FAILED TOOPEN SOCKE 2\n");
}
if (s2Port < 1)
{
printf("FAILED TO BIND SOCKET 2 TO PORT\n");
}
std::thread t1(mysockettest, s1, s2Port);
std::thread t2(mysockettest, s2, s1Port);
t1.join();
t2.join();
close(s1);
close(s2);
}
```
Unforntunately I can't explain the details of they "why" (perhaps someone else can), but I found that adding a global mutex lock to protect the send corrected the instability on the send. The global lock isn't practical for my situation, so instead I implemeneted a simply retry loop on the send (if send() == -1, retry 10 times). While this solution is not ideal, it has proven stable.
Once that stability was resolved, I also saw occasional failures on the read side. With SO_REUSEADDR and binding with port 0 (OS-assignment), it was possible to have both sockets be assigned and bind to the same port, so I removed the SO_REUSEADDR when binding to port 0.

Avoid blocking the program while using TCP in C/C++ and std::array

I'm using Ubuntu and I have a C/C++ application which uses WxWidgets and sends a string over TCP.
It works pretty fine only if the router and the connection are OK, otherwise it gets stuck and I need to manually quit the application.
I call the function in this way:
SendCommand ptr;
if ( ptr.sendcommand(16,16,1) ){
printf("Porta Aperta\n");
} else {
printf("Errore di comunicazione - porta non aperta\n");
}
and this is the function:
int SendCommand::sendcommand(int relay_on, int relay_off, int stop){
printf("eseguo la funzione nella classe\n");
std::array<uint8_t, 8> command1;
std::array<uint8_t, 8> command2;
switch(relay_on){
case 16: command1 = {0x58, 0x01, 0x12, 0x00, 0x00, 0x00, 0x10, 0x7B}; // switch on the relay 16
break;
}
switch(relay_off){
case 16: command2 = {0x58, 0x01, 0x11, 0x00, 0x00, 0x00, 0x10, 0x7A}; // switch off the relay 16
break;
}
int sockfd, n;
struct sockaddr_in servaddr;
std::string serveraddr = "192.168.1.4";
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if ( sockfd < 0 )
{
cerr << "Error creating socket! " << strerror(errno) << endl;
return -1;
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(serveraddr.c_str());
servaddr.sin_port = htons(3000);
if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
{
cerr << "Error connecting socket!" << strerror(errno) << endl;
close(sockfd);
return -1;
}
//Relay #14 per porta bilancia
printf("Apro la porta\n");
int bytes_to_send1 = sizeof(command1);
int bytes_to_send2 = sizeof(command2);
int bytes_sent1 = 0;
int bytes_sent2 = 0;
do
{
n = send(sockfd, command1.data() + bytes_sent1, bytes_to_send1 - bytes_sent1, 0);
if ( n < 0 )
{
cerr << "Error writing to socket!" << strerror(errno) << endl;
close(sockfd);
}
bytes_sent1 += n;
}
while (bytes_sent1 < bytes_to_send1);
n=0;
sleep(stop);
do
{
n = send(sockfd, command2.data() + bytes_sent2, bytes_to_send2 - bytes_sent2, 0);
if ( n < 0 )
{
cerr << "Error writing to socket!" << strerror(errno) << endl;
close(sockfd);
}
bytes_sent2 += n;
}
while (bytes_sent2 < bytes_to_send2);
close(sockfd);
n=0;
return 1;
}
Thanks to the suggestions received in a previous topic, I'm using the notation std::array<uint8_t, 8> command1;to define the arrays for the content to send over the net, but I cannot find a solution to let my program flows correctly even if there are problems on the network.
I tried to use threads or fork() and it works, but is there any other easier solution for this?
P.S. When it get stuck because there is not internet connection, it blocks here:
if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
{
cerr << "Error connecting socket!" << strerror(errno) << endl;
close(sockfd);
return -1;
}
it never enters the if condition.
Several options
Use Boost ASIO
Thread/Processes
set timeout to low (e,g - 5 seconds) so block relatively low amount of time
set socket non blocking and do epoll (involves threads) on it.
For 2 - try using std threads, should be easy to use (you can also go for async + lambda and simplify control flow using futures).
That way code will look and will be more easier to read.
For 3 & 4 - you need to set socket non blocking and do a poll (either through select or epoll) - see fnctl(.., O_NONBLOCK ..) select(). And if you get no error, then you can use the socket as it is (or maybe return it from async and get in future).

Bad file descriptor error while sending data through tcp socket

I want to create data and then send to server. Data from information on each sensor should create in Network.cpp after new sensor was added (each sensor is an new network) and send with client.cpp, I use inheritance to use function add of Network class to client class or vice versa but I need help to use function correctly for my program work. When I run program I get this error:
connect failed. Error: Bad file descriptor
What am I missing?
Network.h:
class Network :public client{
public:
Network();
void add(Sensor new_sensor);
virtual ~Network();
private:
vector<Sensor> sensors;
}
Network.cpp:
void Network::add(const client &a,Sensor new_sensor) {
sensors.push_back(new_sensor);
unsigned int Header[2] = {0xe1,0xe2};
uint16_t u16;
u16 = htons(Header[2]);
memcpy(packet + 0, &u16, 2);
unsigned int SensorSn[4] = { 0x1e, 0x25, 0x71, 0x80 };
uint32_t u32;
u32 = htons(SensorSn[4]);
memcpy(packet + 2, &u32, 4);
uint32_t a32;
unsigned int SensorTemp[4] = { 0x00, 0x00, 0x00, 0x23 };
a32 = htons(SensorTemp[4]);
memcpy(packet + 6, &a32, 4);
a.send_data();
}
client.h:
class client {
public:
client();
void conn(string, int);
void send_data() const;
string receive(int);
virtual ~client();
private:
int sock;
struct sockaddr_in server_addr;
protected:
char packet[10];
};
}
client.cpp:
void client::conn(string address, int port) {
//create socket if it is not already created
if (sock == -1) {
//Create socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
perror("Could not create socket");
}
cout << "Socket created\n" << endl; //doesn't show this line!!!
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(1234);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
while(1){
int m=connect(sock, (struct sockaddr *) &server_addr, sizeof(server_addr));
if (m==-1){
perror("connect failed. Error");
continue;
}
}
cout << "Connected\n"; //doesn't show this line!!!
close(sock);
}
void client::send_data()const {
int n=send(sock, packet, sizeof(packet), 0) ;
if (n==-1){
perror("send failed. Error"); ///my program stop in this line
exit(1);
}
cout << "Data send"<<endl;
close(sock);
}
Did you remember to initialize sock to -1 in your constructor?

Telnet client server session with negotiation

I am trying to write a code for Telnet client server session which sends negotiations between them. Like WILL, WON'T,DO , DON'T. I wrote a basic client-server program using socket programming.
It would be of great help if I could know how to modify client/server as a telnet client server with negotiations. Following is the code:
enter code here
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
char buf1[] = {0xff, 0xfb, 0x18, 0xff, 0xfb, 0x1f};
char buf2[] = {0xff, 0xfc, 0x20, 0xff, 0xfc, 0x23, 0xff, 0xfb, 0x27};
char buf3[] = {0xff, 0xfa, 0x1f, 0x00, 0x78, 0x00, 0x32, 0xff, 0xf0};
char buf4[] = {0xff, 0xfa, 0x27, 0x00, 0xff, 0xf0, 0xff, 0xfa, 0x18, 0x00, 0x41, 0x4e, 0x53, 0x49, 0xff, 0xf0};
char buf5[] = {0xff, 0xfd, 0x03};
char buf6[] = {0xff, 0xfb, 0x01, 0xff, 0xfe, 0x05, 0xff, 0xfc, 0x21};
char buf7[] = {0xff, 0xfc, 0x01};
char buf8[] = {0xff, 0xfd, 0x01};
void read (int sock)
{
char buffer[256];
/* Now read server response */
memset(buffer, 0, sizeof(buffer));
int n = recv( sock, buffer, 255, 0 );
if (n < 0)
{
perror("ERROR reading from socket");
return;
}
printf("%d bytes received buffer is: %s\n", n, buffer);
for (int i = 0; i < n; i++)
printf("%2x ", buffer[i]);
printf("\n");
}
void mwrite (int sock, char * buf, int size)
{
int n = send( sock, buf, size, 0 );
if (n < 0)
{
perror("ERROR writing to socket");
return;
}
printf("Bytes Sent: %d\n", n);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
return(0);
}
portno = atoi(argv[2]);
/* Create a socket point */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("ERROR opening socket");
return(1);
}
server = gethostbyname(argv[1]);
if (server == NULL)
{fprintf(stderr,"ERROR no such host \n");
exit(0);}
//printf("host %s, port %d\n", host.c_str(), portno);
bzero((char *) &serv_addr , sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char*)&serv_addr.sin_addr.s_addr, server->h_length);
//serv_addr.sin_addr.s_addr = inet_addr( host.c_str() ); // ( "127.0.0.1" );
serv_addr.sin_port = htons( portno );
/* Now connect to the server */
if (connect( sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr) ) < 0)
{
perror("ERROR connecting");
return(1);
}
printf("Please enter the message=");
bzero(buffer,256);
fgets(buffer,255,stdin);
n= write(sockfd,buffer,strlen(buffer));
if(n<0)
printf("ERROR writing in socket %d len %d", n, strlen(buffer));
bzero(buffer,256);
n = read(sockfd, buffer, 255);
if(n<0)
perror("ERROR reading from socket");
printf("%s\n",buffer);
close(sockfd);
return 0;
buffer[0] = 0x0d;
buffer[1] = 0x0a;
mwrite ( sockfd, buffer, 2);
printf("read 1 ");
read(sockfd);
mwrite( sockfd, buf1, sizeof(buf1));
sleep(2);
mwrite( sockfd, buf2, sizeof(buf2));
printf("read 2 ");
read(sockfd);
mwrite( sockfd, buf3, sizeof(buf3));
printf("read 3a ");
read(sockfd);
sleep(2);
mwrite( sockfd, buf4, sizeof(buf4));
printf("read 3b ");
read(sockfd);
mwrite( sockfd, buf5, sizeof(buf5));
sleep(2);
mwrite( sockfd, buf6, sizeof(buf6));
printf("read 4 ");
read(sockfd);
mwrite( sockfd, buf7, sizeof(buf7));
sleep(2);
mwrite( sockfd, buf8, sizeof(buf8));
read(sockfd);
mwrite ( sockfd, buffer, 2);
read(sockfd);
return 0;
}
Server.cpp
enter code here :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
void error(char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
//unsigned clilen;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2)
{
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
error("ERROR opening socket");
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
{
error("ERROR on binding");
}
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
{
error("ERROR on accept");
}
bzero(buffer,256);
n = read(newsockfd,buffer,255);
if (n < 0)
{
error("ERROR reading from socket");
}
printf("Here is the message: %s\n",buffer);
n = write(newsockfd,"I got your message",18);
if (n < 0)
{
error("ERROR writing to socket");
}
return 0;
}
Thanks in advance.
[It started to be too much for comments, so I write as an answer instead.]
As for your problem, it's actually not a single problem but two intermingled problems: Buffering and negotiation. You need buffering because TCP is a streaming protocol, a receive call might receive only a part of a telnet message, and a send call might send only a part of a telnet message. The second problem is the negotiation, for which you need a so-called state machine. And you need one state per option.
You also need to read and understand RFC854 and RFC855. See the Telnet Wikipedia article for a comprehensive list of RFC's.
For the option negotiation, WILL and WONT is responded by DO or DONT. You should generally not send a DO or DONT unless you already received a WILL or WONT. For starters, until you implemented proper handing of the options, I recommend you always answer with DONT whenever you get a WILL (and or course a WONT) message. Don't send WILL or WONT unless you really need to negotiate about an option.
More implementation-wise, I recommend four state tables, one each for WILL, WONT, DO and DONT that you have sent. Those tables contain simple boolean values that tells you if you have sent the corresponding message to the peer. These four table assumes that any unrecognized option you receive is replied with a DONT or WONT.
If you send a WILL then you mark that in the corresponding state-table, so that when you receive a DO or DONT for the option you know that it was you that initiated the negotiation.