extra newlines at end of file transported over tcp - c++

I have two programs, recvfile.py and sendfile.cpp. They work except that I end up with a bunch of extra newline characters at the end of the new file. I don't know how the extra spaces get there. I know the problem is sender side, because the same doesn't happen when I use python's sendall() function to send the file.
Here are the files:
jmm_sockets.c
#include <winsock.h>
#include <stdio.h>
#include <stdlib.h>
int getServerSocket(int port)
{
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,0), &wsaData) != 0){
fprintf(stderr, "WSAStartup() failed\n");
exit(1);
}
// create socket for incoming connections
int servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(servSock == INVALID_SOCKET){
fprintf(stderr, "Oops: socket() failed %d\n", WSAGetLastError());
exit(1);
}
// construct local address structure
struct sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = INADDR_ANY;
servAddr.sin_port = htons(port);
// bind to the local address
int servAddrLen = sizeof(servAddr);
if(bind(servSock, (SOCKADDR*)&servAddr, servAddrLen) == SOCKET_ERROR){
fprintf(stderr, "Oops: bind() failed %d\n", WSAGetLastError());
exit(1);
}
return servSock;
}
int getClientSocket(char* host, int port)
{
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,0), &wsaData) != 0){
fprintf(stderr, "Oops: WSAStartup() failed");
exit(1);
}
// create tcp socket
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(socket<0){
fprintf(stderr, "Oops: socket() failed %d\n", WSAGetLastError());
exit(1);
}
// set up serverAddr structure
struct sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr(host);
servAddr.sin_port = htons(port);
// connecet to server address
if(connect(sock, (SOCKADDR*)&servAddr, sizeof(servAddr)) < 0){
fprintf(stderr, "Oops: connect() failed. %d\n", WSAGetLastError());
exit(1);
}
return sock;
}
sendfile.cpp:
#include "jmm_sockets.h"
#include <windows.h>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <sys/stat.h>
using namespace std;
int main(int argc, char** argv)
{
int port;
string host;
string filename;
if(argc==2){
cout << "Host: ";
cin >> host;
cout << "Port: ";
cin >> port;
filename = argv[1];
}else if (argc == 4){
host = argv[1];
port = atoi(argv[2]);
filename = argv[3];
}else{
cerr << "Usage: " << argv[0] << " [<host> <port>] <filename>" << endl;
exit(1);
}
// open file for reading
ifstream fin;
fin.open(filename.c_str());
if(fin.fail()){
cerr << "Error: opening " << filename << " failed. " << endl;
exit(1);
}
// get file size
fin.seekg(0, ios::end);
int size = fin.tellg();
fin.seekg(0, ios::beg);
// open socket for sending
int sock = getClientSocket((char*)host.c_str(), port);
// send file size
char buffer[16];
itoa(size, buffer, 10);
int i;
for(i=0; i<strlen(buffer); i++){
if(send(sock, &buffer[i], 1, 0)!=1){
cerr << "Error: send() failed " << WSAGetLastError() << endl;
exit(1);
}
}
char c = '\n';
if(send(sock, &c, 1, 0)!=1){
fprintf(stderr, "Error: send() failed %d\n", WSAGetLastError());
exit(1);
}
// recv y or n
int recvMsgSize = recv(sock, &c, 1, 0);
if(recvMsgSize!=1){
fprintf(stderr, "Error: recv() failed %d\n", WSAGetLastError());
exit(1);
}
if(c=='y'){
// send entire file
int readSoFar = 0;
while(readSoFar < size){
fin.get(c);
if(send(sock, &c, 1, 0)!=1){
cerr << "Error: send() failed " << WSAGetLastError() << endl;
exit(1);
}
readSoFar++;
}
}else if (c=='n'){
// leave
cout << "Remote host declined file." << endl;
}
fin.close();
closesocket(sock);
WSACleanup();
//
return 0;
}
and finally, recvfile.py:
import sys
from jmm_sockets import *
import yesno
if len(sys.argv) != 2:
print "Usage: ", argv[0], "<port>"
s = getServerSocket(None, int(sys.argv[1]))
conn, addr = s.accept()
buffer = None
filelen = str()
# receive filesize
while 1:
buffer = conn.recv(1)
if buffer == '\n':
# give it a rest
break
else:
filelen = filelen + buffer
# prompt user to accept file
filelen = int(filelen)
print "file size = ", filelen,
userChoice = yesno.yesno("Accept?")
conn.send(userChoice)
# conditionally accecpt file
if bool(userChoice):
filename = raw_input("What do you want to call the file? ")
f = open(filename, 'w')
buffer = None
data = str()
recvdBytes = 0
while recvdBytes < filelen:
buffer = conn.recv(1)
recvdBytes = recvdBytes + 1
data = data + buffer
print "File: ",
f.write(data)
print "written"
conn.close()

The reason you're ending up with extra newlines is because you're sending extra newlines across the socket, which is because you try to send more data than you should.
If you checked the fail() state of your input file fin, you'd discover that it's failing on the last several calls to fin.get(c), so the value of c remains unchanged -- it stays as a newline character, which is the last character in the input file.
This is happening because of CRLF translation: the file size you're using (the size variable) is the raw file size on disk, counting all of the CRs. But, when you open it up in text mode and read it in one byte at a time, the standard library silently translates all CRLFs into LFs, so you don't send the CRs across the socket. Hence, the number of extra newlines you get at the end of this process is equal to the number of newlines that were in the original file.
The way to fix this is to open the file in binary mode to disable CRLF translation:
fin.open(filename.c_str(), ios::in | ios::binary);
Furthermore, you shouldn't be sending the file one byte at a time -- this is horrendously slow. If you're unlucky, you'll be sending an entire packet for each byte. If you're lucky, your OS's network stack will accumulate these multiple sends into larger packets (don't depend on that), but even then you're still making a huge number of system calls into the kernel.
Consider refactoring your code to make fewer calls to send() and recv(), where you pass a larger number of bytes per call, e.g.:
// Just use one call to send instead of looping over bytes and sending one
// byte at a time. Simpler and faster!
send(sock, buffer, strlen(buffer), 0);

Related

recvfrom only receive few packets after that it goes in waiting state

Hi I am new in Socket Programming and try to create a client server applciation using in which my server is Camera and client in my C++ application.
When I see the packet transfer between computer and camera it showing that camera is sending more than 150000 packets after that it stops. But when I am receving that I am able to receive 400 - 450 packets at a time after that the recvfrom function goes to waiting state. and If I again run that exe file without stopping the previous one it again receive 400-450 packets.
Code for Receving Packets
SOCKET out1 = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
if (out1 == INVALID_SOCKET)
{
cout << out1 << endl;
}
server.sin_family = AF_INET;
server.sin_port = htons(3956);
inet_pton(AF_INET, "192.168.1.140", &server.sin_addr);
int serverLength = sizeof(server);
connect(out1, (sockaddr*)&server, serverLength);
while (1)
{
memset(buf, 0, sizeof(buf));
int bytesIn = recvfrom(out1, buf, 1444, 0, (sockaddr*)&server, &serverLength);
if (bytesIn > 0)
{
cout << "Image Received :" << bytesIn <<packet_counter << endl;
packet_counter++;
}
else
{
cout << "Not Received : " << endl;
}
}
I am running the .exe with the administrator rights.
So can anyone please tell me why the recvfrom function is going in waiting state.
Thanks in Advance.
EDIT:-
Sorry that I am providing the whole code.
#include <stdio.h>
#include <Windows.h>
#include <thread>
#include <WinSock2.h>
// Library
#pragma comment(lib, "ws2_32.lib")
using namespace std;
//***** Function Decleration *****//
void _packetConfig(SOCKET);
void _sendPacket(SOCKET, const char*, int, int);
// Global Variable
sockaddr_in server;
//***** Main Function *****//
void main(char argc, char* argv[])
{
WSADATA data;
WORD version = MAKEWORD(2, 2);
if(WSAStartup(version, &data) == SOCKET_ERROR)
{
cout << "Can't Start Socket" << WSAGetLastError<<endl;
return;
}
char buf[2000];
SOCKET out1 = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
if (out1 == INVALID_SOCKET)
{
cout << out1 << endl;
}
server.sin_family = AF_INET;
server.sin_port = htons(3956);
inet_pton(AF_INET, "192.168.1.140", &server.sin_addr);
int serverLength = sizeof(server);
connect(out1, (sockaddr*)&server, serverLength);
int packet_counter = 0;
SOCKET out = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
_packetConfig(out);
cout << "Inside Main" << endl;
while (1)
{
//connect(out1, (sockaddr*)&server, serverLength);
memset(buf, 0, sizeof(buf));
int bytesIn = recvfrom(out1, buf, 1444, 0, (sockaddr*)&server, &serverLength);
if (bytesIn > 0)
{
cout << "Image Received :" << bytesIn <<packet_counter << endl;
packet_counter++;
}
else
{
cout << "Not Received : " << endl;
}
}
WSACleanup();
}
//***** Function to Send Bytes to the Camera *****//
void _sendPacket(SOCKET sock, const char* s, int len, int i)
{
int sendOk = sendto(sock, (const char*)s, len, 0, (sockaddr*)&server, sizeof(server));
if (sendOk == SOCKET_ERROR)
{
cout << "Didn't Work" << WSAGetLastError() << endl;
}
else
{
cout << "\nSend Succesfully" << " " << i << endl;
}
char buf[2000];
int serverLength = sizeof(server);
int bytesIn = recvfrom(sock, buf, 2000, 0, (sockaddr*)&server, &serverLength);
if (bytesIn > 0)
{
cout << "Message Received :" << bytesIn << endl;
}
}
//***** Function to call the _sendPacket function and send commands to the Camera *****//
void _packetConfig(SOCKET sock)
{
// 59 Commands and every command call _snedPacket function to send commands to camera it will working properly
}
In the above code I have to first send this 59 commands written in _packetConfig function then only camera will send Image packets I am receiving the reply of all that commands.
When I run wireshark also with that code I can see that after these 59 commands
the camera is giving 3580*51 packets.i.e 51 frames and each frame contain 3580 packets
Thank you for posting your code. There are actually a few things wrong with it so first I will post some code that works as a reference and then mention the major issues I noticed with yours afterwards.
OK, here is some code that works for me:
#include <WinSock2.h> // ** before** windows.h
#include <WS2tcpip.h>
#include <iostream>
#include <stdio.h>
#include <Windows.h>
#include <assert.h>
#pragma comment (lib, "ws2_32.lib")
const int port = 3956;
// main
int main (char argc, char* argv[])
{
WSADATA wsadata;
WORD version = MAKEWORD(2, 2);
int err = WSAStartup (MAKEWORD (2, 2), &wsadata);
if (err)
{
std::cout << "WSAStartup failed, error: " << err << std::endl;
return 255;
}
char buf [1444];
bool send = argc > 1 && _stricmp (argv [1], "send") == 0;
if (send)
{
// Send
SOCKET skt_out = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
assert (skt_out != INVALID_SOCKET);
sockaddr_in destination_address = { };
destination_address.sin_family = AF_INET;
destination_address.sin_port = htons (port);
inet_pton (AF_INET, "192.168.1.2", &destination_address.sin_addr);
memset (buf, 'Q', sizeof (buf));
printf ("Sending: ");
for ( ; ; )
{
sendto (skt_out, buf, sizeof (buf), 0, (const sockaddr *) &destination_address, sizeof (destination_address));
printf (".");
Sleep (50);
}
closesocket (skt_out);
WSACleanup ();
return 0;
}
// Receive
SOCKET skt_in = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
assert (skt_in != INVALID_SOCKET);
int receive_buffer_size = 65536;
if ((setsockopt (skt_in, SOL_SOCKET, SO_RCVBUF, (const char *) &receive_buffer_size, sizeof (int)) ) < 0)
std::cout << "Could not set SO_RCVBUF, error: " << WSAGetLastError () << std::endl;
sockaddr_in receive_address = { };
receive_address.sin_family = AF_INET;
receive_address.sin_port = htons (port);
receive_address.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind (skt_in, (const sockaddr *) &receive_address, sizeof (receive_address)) == -1)
{
std::cout << "bind failed , error: " << WSAGetLastError () << std::endl;
return 255;
}
int packetCounter = 0;
printf ("Receiving: ");
for ( ; ; )
{
int bytesIn = recvfrom (skt_in, buf, sizeof (buf), 0, NULL, 0);
if (bytesIn > 0)
std::cout << "Packet received:" << bytesIn << " bytes (" << ++packetCounter << ")" << std::endl;
else
std::cout << "Receive error: " << WSAGetLastError () << std::endl;
}
closesocket (skt_in);
WSACleanup ();
return 0;
}
To run this in 'send' mode, specify send as the first argument on the command line. Otherwise it acts as a receiver (aka server).
So what's wrong with your code? Well, in no particular order:
as we already said, you shouldn't be using SOCK_RAW
you need to call bind on the receiving socket so that it knows what port to listen on. The sockaddr *from parameter to recvfrom doesn't mean what you think it means (please check the docs). You will see I pass this as NULL.
you were misinterpreting the return value from WSAStartup. Again, please check the docs.
But having said all that, it was essentially the call to bind that you were missing. I rewrote the code because yours is rather messy.
Also, important detail, UDP doesn't guarantee delivery - there are a number of reasons why a packet that has been sent does not get received or might even get received out of sequence (does your camera sequence the packets in some way?)
You need to cater for that in the logic of your application (and it that's a problem, it's better to use TCP, which does guarantee packet delivery and sequencing).

GET and PUT commands with C++ Server-Client

I'm trying to create a server, client put and get method but I don't really know where to start, how do I make the server run the commands I process. Any help would be much appreciated.
Client file
void Copy(char *filename1,char *filename2);
int main(int argc, char **argv)
{
if(argc == 3)
{
int Sockfd;
sockaddr_in ServAddr;
hostent *HostPtr;
int Port = atoi(argv[2]);
int BuffSize = 0;
// get the address of the host
HostPtr = Gethostbyname(argv[1]);
if(HostPtr->h_addrtype != AF_INET)
{
perror("Unknown address type!");
exit(1);
}
memset((char *) &ServAddr, 0, sizeof(ServAddr));
ServAddr.sin_family = AF_INET;
ServAddr.sin_addr.s_addr = ((in_addr*)HostPtr->h_addr_list[0])->s_addr;
ServAddr.sin_port = htons(Port);
// open a TCP socket
Sockfd = Socket(AF_INET, SOCK_STREAM, 0);
// connect to the server
Connect(Sockfd, (sockaddr*)&ServAddr, sizeof(ServAddr));
char userI[256];
// write a message to the server
int dupSockfd = dup(Sockfd);
FILE* writeFile = fdopen(Sockfd, "w");
FILE* readFile = fdopen(dupSockfd, "r");
setlinebuf(writeFile);
char writerBuff[256];
for(;;)
{
cout << "ftp> ";
if(fgets(userI, sizeof(userI), stdin))
{
if(userI == "exit")
{
return 1;
}
else
{
string cmd, f1, f2;
istringstream iss(userI, istringstream::in);
iss >> cmd >> f1 >> f2;
cout << cmd << "." << f1 << "." << f2 << endl;
if(cmd == "get")
{
write(Sockfd, "get", sizeof("get"));
Copy(f1, f2);
}
}
}
}
close(Sockfd);
}
else
{
cout << "Incorrect commands for running... try './client (hostname) (port)'" << endl;
return 1;//
}
return 0;//
}
void Copy(char *filename1,char *filename2) {
const int BUFSIZE=2048;
char buffer[BUFSIZE];
ifstream fin;
ofstream fout;
long filelen, bytesRemaining, bytes;
// Open the file to be transferred, check it exists.
fin.open( filename1);
if (!fin.good())
{
cerr << "Problems opening \"" << filename1 << "\" (" << errno << "): " << strerror(errno) << endl;
exit(1);
}
fout.open(filename2);
if (!fout.good())
{
cerr << "Problems opening \"" << filename2 << "\" (" << errno << "): " << strerror(errno) << endl;
exit(1);
}
// Determine the file's length.
fin.seekg(0,ios::end);
if(fin.fail()) cerr<<"seekg() fail!\n";
filelen = fin.tellg();
if(fin.fail()) cerr<<"tellg() fail!\n";
fin.seekg(0, ios::beg);
if(fin.fail()) cerr<<"seekg() fail!\n";
// Copy the file data.
bytesRemaining = filelen;
while (bytesRemaining > 0)
{
bytes = bytesRemaining > BUFSIZE ? BUFSIZE : bytesRemaining;
fin.read(buffer,bytes);
if(fin.fail()){
cerr<<"read() error\n";
exit(1);
}
fout.write(buffer,bytes);
if(fout.fail()){
cerr<<"write() error\n";
exit(1);
}
bytesRemaining -= bytes;
}
fin.close();
fout.close();
}
Server file
int main(int argc, char **argv)
{
if(argc == 2)
{
int Sockfd, NewSockfd, ClntLen;
sockaddr_in ClntAddr, ServAddr;
int Port = atoi(argv[1]);
char String[MAX_SIZE];
int Len;
// open a TCP socket (an Internet stream socket)
Sockfd = Socket(AF_INET, SOCK_STREAM, 0); // socket() wrapper fn
// bind the local address, so that the client can send to server
memset((char*)&ServAddr, 0, sizeof(ServAddr));
ServAddr.sin_family = AF_INET;
ServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
ServAddr.sin_port = htons(Port);
int opt = 1;
setsockopt(Sockfd,SOL_SOCKET,SO_REUSEADDR, (void*)opt, sizeof(opt));
Bind(Sockfd, (sockaddr*) &ServAddr, sizeof(ServAddr));
// listen to the socket
Listen(Sockfd, 5);
int RecvMsgSize;
for(;;)
{
// wait for a connection from a client; this is an iterative server
ClntLen = sizeof(ClntAddr);
NewSockfd = Accept(Sockfd, (sockaddr*)&ClntAddr, &ClntLen);
if((RecvMsgSize = recv(ClntSocket, EchoBuffer, RCVBUFSIZE, 0)) < 0)
{
perror("recv() failed");
exit(1);
}
// read a message from the client
Len = read(NewSockfd, String, MAX_SIZE);
String[Len] = 0;// make sure it's a proper string
cout<< String << endl;
close(NewSockfd);
}
}
else
{
cout << "Incorrect commands for running... try './server (port)'" << endl;
return 1;//
}
return 0;//
}
You want to create a Web server that will process GET and PUT requests? You first need to read how the http works. Let me explain in simple terms.
Try to develop your server first and connect it to a browser :
1.Make your server listen on port 80 - this is a must
2.Create a buffer that will read the request from the browser(client), as you do in this part of your code:
if((RecvMsgSize = recv(ClntSocket, EchoBuffer, RCVBUFSIZE, 0)) < 0)
{
perror("recv() failed");
exit(1);
}
// read a message from the client
Len = read(NewSockfd, String, MAX_SIZE);
String[Len] = 0;// make sure it's a proper string
cout<< String << endl;
close(NewSockfd);
so this String object is your buffer, it will contain the http request.
3.You need to parse the request. Parse the request to see whether the method is GET PUT POST or etc.
This is a sample GET request :
https://marketing.adobe.com/developer/documentation/data-insertion/r-sample-http-get
4.Then you need to send the proper response back to the client in this case the browser:
http://pastebin.com/BPnVHym5
5.Connect your browser to the server by typing your ip adress in the addressbar
I would honestly use a C++ REST API library to do the work. You can find one called "Casablanca."
Here's an example on how to use it for making a client: https://casablanca.codeplex.com/wikipage?title=Http%20Client%20Tutorial
Here is an example on how to create a server: https://casablanca.codeplex.com/wikipage?title=HTTP%20Listener&referringTitle=Documentation
Maybe this will get you started.

Why receiving data from server has a segmentation fault error (No error in sending)?

This error has destroyed my day. This is my second client server program. Server is iterative type. The functionality is 1.server is running all the time.
2.Client send a file name to server.
3.Server opens the file and process on its data and send information back to client.
But in the point that client receive data it produce a segmentation error. Even it can read inside the packet, but only "filename".
In fact server is opening a file and open linux dictionary file. It searches for any spelling problem etc. Finally it has line number, word and suggested word.
I have checked inside the list in server side and list has no error.
here is an abstract of my code. I appreciate if anyone can find the bug. I copy paste all code except processing on the file. Apologist in advance for long code.
Client side:
#include <pthread.h>
#include <regex.h>
#include "wrappers.h"
struct SType{
int Num;
char Word[20];
char sugg[20];
};
struct DataPktType
{
list<SType> MyList;
char filename[MAX_SIZE], message[MAX_SIZE];
int numslaves;
};
int main(int argc, char **argv){
int Sockfd;
sockaddr_in ServAddr;
char ServHost[] = "localhost";
hostent *HostPtr;
int Port = SERV_TCP_PORT;
DataPktType DataPkt;
DataPktType recDataPkt;
string filename, tempstr;
if (argc == 5){
strcpy(ServHost, argv[1]);
Port = atoi(argv[2]);
filename = string(argv[3]);
cout<<"filename= "<<filename<<endl;
DataPkt.numslaves = atoi(argv[4]);
} else{
cout << "Usage: \"client <server address> <port> <textfile> <numThreads>\".\n" << endl;
exit(1);
}
// Get the address of the host
HostPtr = Gethostbyname(ServHost);
if(HostPtr->h_addrtype != AF_INET)
{
perror("Unknown address type!");
exit(1);
}
memset((char *) &ServAddr, 0, sizeof(ServAddr));
ServAddr.sin_family = AF_INET;
ServAddr.sin_addr.s_addr = ((in_addr*)HostPtr->h_addr_list[0])->s_addr;
ServAddr.sin_port = htons(Port);
// Open a TCP socket
Sockfd = Socket(AF_INET, SOCK_STREAM, 0);
// Connect to the server
Connect(Sockfd, (sockaddr*)&ServAddr, sizeof(ServAddr));
strcpy(DataPkt.filename, argv[3]);
DataPkt.numslaves = 6;
// Write and read a message to/from the server
write(Sockfd, (char*)&DataPkt, sizeof(DataPktType));
read(Sockfd, (char*)&recDataPkt, sizeof(DataPktType));
cout<<"here"<<endl;
cout << setw(30) << left << "Filename:" << setw(20) << right << DataPkt.filename << endl;
list<SType> MyList2;
MyList2 = DataPkt.MyList;
cout<<"size= "<<MyList2.size()<<endl;
for (list<SType>::iterator it=MyList2.begin(); it!=MyList2.end(); it++)
cout << ' ' << it->Num << ' ' << it->Word << endl;
cout << "Finished\n";
close(Sockfd);
return 0;
}
Server side:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstream.h>
#include <list>
#include <iomanip>
#include <pthread.h>
#include "wrappers.h"
#include<cstdlib>
#include<fstream>
#include<iostream>
#include<sstream>
#include <algorithm>
#define BUFSIZE 10
#define gNumThreads 6
using namespace std;
struct SType{
int Num;
char Word[20];
char sugg[20];
};
struct DataPktType
{
list<SType> MyList;
char filename[MAX_SIZE], message[MAX_SIZE];
int numslaves;
};
int main(int argc, char **argv){
int Sockfd, NewSockfd, ClntLen, Port = SERV_TCP_PORT;
sockaddr_in ClntAddr, ServAddr;
DataPktType DataPkt;
if (argc == 2){
Port = atoi(argv[1]);
}
// Open a TCP socket (an Internet stream socket)
Sockfd = Socket(AF_INET, SOCK_STREAM, 0); // socket() wrapper fn
// Setup server for development
setsockopt(Sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
// Bind the local address, so that the client can send to server
memset((char*)&ServAddr, 0, sizeof(ServAddr));
ServAddr.sin_family = AF_INET;
ServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
ServAddr.sin_port = htons(Port);
Bind(Sockfd, (sockaddr*) &ServAddr, sizeof(ServAddr));
// Listen to the socket
Listen(Sockfd, 5);
for(;;)
{
// Wait for a connection from a client; this is an iterative server
ClntLen = sizeof(ClntAddr);
NewSockfd = Accept(Sockfd, (sockaddr*)&ClntAddr, &ClntLen);
if(NewSockfd < 0)
{
perror("Can't bind to local address!");
}
// Read a message from the client
read(NewSockfd, (char*)&DataPkt, sizeof(DataPktType));
string line;
ifstream myfile (DataPkt.filename);
if (myfile.is_open())
{
--Here is some operation I deleted to make file shorter ---
if(!found)
{
/* Add suggestion to the list */
SType S;
S.Num = lineNo;
strcpy(S.Word, result);
strcpy(S.sugg, sugg);
MyList2.push_back(S);
cout<<lineNo<<" "<<result<<" "<<sugg<<endl;
cout<<"Not found in dictionary"<<endl;
}
else
{
cout<<"found: "<<result<<" in dictionary"<<endl;
}
}
}
myfile.close();
cout<<"List before write"<<endl;
for (list<SType>::iterator it=MyList2.begin(); it!=MyList2.end(); it++)
cout << ' ' << it->Num << ' ' << it->Word << endl;
/*Send suggestion back to the client*/
DataPktType retPack;
retPack.MyList = MyList2;
//DataPkt.filename
strcpy(retPack.filename,"behzad");
write(NewSockfd, (char*)&retPack, sizeof(DataPktType));
}
else {cout << "Unable to open file"; exit(1);}
}
close(NewSockfd);
/* exit the program */
return(0);
}
output:
serverside:
1 bernard behead
Not found in dictionary
List before write
lineNo: 1 word: behzad sugg: behead
clientside:
$ ./client localhost 19431 carol.txt 6
filename= carol.txt
Finished
Segmentation Fault
You are not doing any kind of serialization over your data before send or receive.
write(Sockfd, (char*)&DataPkt, sizeof(DataPktType));
read(Sockfd, (char*)&recDataPkt, sizeof(DataPktType));
That part is completely wrong, you have a std::list into your struct, you need first to process that data before send it.

C++ strange socket data

Hey guys, here is my code.
int main() {
char buffer[BUFSIZE];
// define our address structure, stores our port
// and our ip address, and the socket type, etc..
struct sockaddr_in addrinfo;
addrinfo.sin_family = AF_INET;
addrinfo.sin_port = htons(PORT);
addrinfo.sin_addr.s_addr = INADDR_ANY;
// create our socket.
int sock;
if ( (sock = socket(addrinfo.sin_family, SOCK_STREAM, 0)) < 0) {
cout << "Error in creating the socket.";
}
// bind our socket to the actual adress we want
if (bind(sock, (struct sockaddr*)&addrinfo, sizeof(addrinfo)) != 0) {
cout << "Error in binding.";
}
// open the socket up for listening
if (listen(sock, 5) != 0) {
cout << "Error in opening listener.";
}
cout << "Waiting for connections...." << endl;
char *msg = "Success! You are connected.\r\n";
// continuously accept new connections.. but no multithreading.. yet
while(1) {
struct sockaddr_in client_addr;
socklen_t sin_size = sizeof(client_addr);
if(int client = accept(sock, (struct sockaddr*)&client_addr, &sin_size)) {
cout << "Recived new connection from " << inet_ntoa(client_addr.sin_addr) << endl;
send(client, msg, strlen(msg), 0);
while(1) {
send(client, buffer, recv(client, buffer, BUFSIZE, 0), 0);
cout << buffer << endl;
strcpy(buffer, "");
}
} else {
cout << "Error in accepting new connection." << endl;
}
}
close(sock);
return 0;
}
Now, I'm very new to sockets, Im just sort of trying to get a feel for them but I do have some experience with sockets in PHP. I'm using telnet via putty on my linux machine to test this, I don't know if thats causing any issues but the server is outputting some strange characters and I don't know why. I think it has something to do with the buffer, but I'm not really sure. I can send things like "hi" to the server via telnet and it outputs them just fine and sends them back to me but when I send things like "hoobla" it starts the funky character stuff. Any suggestions would be helpful!
Thanks in advance!
You're getting rubbish printed out because recv does not null-terminate your buffer.
The important section in the below code is:
int num = recv(client,buffer,BUFSIZE,0);
if (num < 1) break;
send(client, ">> ", 3, 0); // <<-- Nice to have.
send(client, buffer, num, 0);
buffer[num] = '\0'; // <<-- Really important bit!
if (buffer[num-1] == '\n') // <<-- Nice to have.
buffer[num-1] = '\0'; // <<-- Nice to have.
cout << buffer << endl;
which will properly terminate your buffer before trying to print it, as well as remove the trailing newline if present (and allow the client to distinguish between input and echoed lines).
This one (a complete program) works a little better:
using namespace std;
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUFSIZE 1000
#define PORT 1234
int main() {
char buffer[BUFSIZE];
// define our address structure, stores our port
// and our ip address, and the socket type, etc..
struct sockaddr_in addrinfo;
addrinfo.sin_family = AF_INET;
addrinfo.sin_port = htons(PORT);
addrinfo.sin_addr.s_addr = INADDR_ANY;
// create our socket.
int sock;
if ( (sock = socket(addrinfo.sin_family, SOCK_STREAM, 0)) < 0) {
cout << "Error in creating the socket.";
return -1;
}
// bind our socket to the actual adress we want
if (bind(sock, (struct sockaddr*)&addrinfo, sizeof(addrinfo)) != 0) {
cout << "Error in binding.";
return -1;
}
// open the socket up for listening
if (listen(sock, 5) != 0) {
cout << "Error in opening listener.";
return -1;
}
char *msg = "Success! You are connected.\r\n";
// continuously accept new connections.. but no multithreading.. yet
while(1) {
cout << "Waiting for connections...." << endl;
struct sockaddr_in client_addr;
socklen_t sin_size = sizeof(client_addr);
if(int client =
accept(sock, (struct sockaddr*)&client_addr, &sin_size))
{
cout << "Recieved new connection from "
<< inet_ntoa(client_addr.sin_addr) << endl;
send(client, msg, strlen(msg), 0);
while(1) {
int num = recv(client,buffer,BUFSIZE,0);
if (num < 1) break;
send(client, ">> ", 3, 0);
send(client, buffer, num, 0);
buffer[num] = '\0';
if (buffer[num-1] == '\n')
buffer[num-1] = '\0';
cout << buffer << endl;
strcpy(buffer, "");
}
} else {
cout << "Error in accepting new connection." << endl;
}
}
close(sock);
return 0;
}
On the client side:
$ telnet 127.0.0.1 1234
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Success! You are connected.
hello
>> hello
my name is pax
>> my name is pax
and you?
>> and you?
<CTRL-D>
Connection closed by foreign host.
and, on the server side:
$ ./testprog
Waiting for connections....
Recived new connection from 127.0.0.1
hello
my name is pax
and you?
Waiting for connections....
The problem is that buffer is not guaranteed to contain a string-terminating null character. Add the line buffer[BUFSIZE-1] = '\0' just before your cout << buffer.
Even better, actually record how many bytes were received, and use that information to determine if you overran your buffer.

bind() fails with windows socket error 10038

I'm trying to write a simple program that will receive a string of max 20 characters and print that string to the screen.
The code compiles, but I get a bind() failed: 10038. After looking up the error number on msdn (socket operation on nonsocket), I changed some code from
int sock;
to
SOCKET sock
which shouldn't make a difference, but one never knows.
Here's the code:
#include <iostream>
#include <winsock2.h>
#include <cstdlib>
using namespace std;
const int MAXPENDING = 5;
const int MAX_LENGTH = 20;
void DieWithError(char *errorMessage);
int main(int argc, char **argv)
{
if(argc!=2){
cerr << "Usage: " << argv[0] << " <Port>" << endl;
exit(1);
}
// start winsock2 library
WSAData wsaData;
if(WSAStartup(MAKEWORD(2,0), &wsaData)!=0){
cerr << "WSAStartup() failed" << endl;
exit(1);
}
// create socket for incoming connections
SOCKET servSock;
if(servSock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)==INVALID_SOCKET)
DieWithError("socket() failed");
// construct local address structure
struct sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = INADDR_ANY;
servAddr.sin_port = htons(atoi(argv[1]));
// bind to the local address
int servAddrLen = sizeof(servAddr);
if(bind(servSock, (SOCKADDR*)&servAddr, servAddrLen)==SOCKET_ERROR)
DieWithError("bind() failed");
// mark the socket to listen for incoming connections
if(listen(servSock, MAXPENDING)<0)
DieWithError("listen() failed");
// accept incoming connections
int clientSock;
struct sockaddr_in clientAddr;
char buffer[MAX_LENGTH];
int recvMsgSize;
int clientAddrLen = sizeof(clientAddr);
for(;;){
// wait for a client to connect
if((clientSock=accept(servSock, (sockaddr*)&clientAddr, &clientAddrLen))<0)
DieWithError("accept() failed");
// clientSock is connected to a client
// BEGIN Handle client
cout << "Handling client " << inet_ntoa(clientAddr.sin_addr) << endl;
if((recvMsgSize = recv(clientSock, buffer, MAX_LENGTH, 0)) <0)
DieWithError("recv() failed");
cout << "Word in the tubes: " << buffer << endl;
closesocket(clientSock);
// END Handle client
}
}
void DieWithError(char *errorMessage)
{
fprintf(stderr, "%s: %d\n", errorMessage, WSAGetLastError());
exit(1);
}
The problem is with
servSock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)==INVALID_SOCKET
which does not associate as you think it does. Why would you even want to write something like that, what's wrong with
SOCKET servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(servSock == INVALID_SOCKET)
DieWithError("socket() failed");
?