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.
Related
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).
I am able to make client and server connect, but not chat with each other. I can only make the server receive messages and the client can only to send them...but it doesn't work the other way around.
Relevant server code:
while(recv(acceptedSocket,buffer,255,0)){
std::cout << buffer << std::endl;
memset(buffer,0,sizeof(buffer));
n = send(acceptedSocket,"Message received!", 18 , 0);
if(n < 0)
error("Failed sending data!");
}
Relevant client code:
do{
memset(buffer,0,sizeof(buffer));
std::cout << "Enter your message: " << std::endl;
std::cin.getline(buffer,255);
n = send(connectingSocket,buffer,strlen(buffer),0);
} while(n > 0);
Can I make server and client send and receive messages without multi-threading or do I have to multi-thread?
All code
Server:
int main() {
int listeningSocket,acceptedSocket,port,n;
unsigned int clientLength;
char buffer[256];
struct sockaddr_in server_address , client_address;
std::cout << "ENTER PORT(ABOVE 2000):";
std::cin >> port;
if(port < 2000){
error("NO PORT PROVIDED");
}
listeningSocket = socket(AF_INET,SOCK_STREAM,0);
if(listeningSocket < 0)
error("FAILED CREATING A SOCKET!");
memset((char * ) &server_address,0,sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = INADDR_ANY;
server_address.sin_port = htons(port);
if(bind(listeningSocket,(struct sockaddr *) &server_address,sizeof(server_address)) < 0)
error("BINDING FAILED!");
listen(listeningSocket,5);
clientLength = sizeof(client_address);
acceptedSocket = accept(listeningSocket,(struct sockaddr *) &client_address,&clientLength);
if(acceptedSocket < 0)
error("ACCEPTING FAILED!");
std::cout << "Connection incoming from " << client_address.sin_addr.s_addr << std::endl;
while(recv(acceptedSocket,buffer,255,0)){
std::cout << buffer << std::endl;
memset(buffer,0,sizeof(buffer));
n = send(acceptedSocket,"Message received!", 18 , 0);
if(n < 0)
error("Failed sending data!");
}
}
Client:
int main() {
int connectingSocket,portNo,n;
struct sockaddr_in server_address;
struct hostent *server;
char buffer[256];
std::cout << "Enter server's IP:";
char * ipHolder;
std::cin >> ipHolder;
server = gethostbyname(ipHolder);
if(server == NULL){
error("NO SUCH HOST!");
}
std::cout << "ENTER PORT:";
std::cin >> portNo;
connectingSocket = socket(AF_INET,SOCK_STREAM,0);
if(connectingSocket < 0)
error("FAILED OPENING A SOCKET!");
memset(&server_address,0,sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(portNo);
memcpy(server->h_addr_list,&server_address.sin_addr.s_addr,server->h_length);
if(connect(connectingSocket,(sockaddr *)&server_address,sizeof(server_address)) < 0)
error("CONNECTION FAILURE!");
std::cout << "CONNECTION MADE!" << std::endl;
std::cin.ignore();
do{
memset(buffer,0,sizeof(buffer));
std::cout << "Enter your message: " << std::endl;
std::cin.getline(buffer,255);
n = send(connectingSocket,buffer,strlen(buffer),0);
}while(n > 0);
return 0;
}
Thank you!
The easiest most straight-forward solution is making the server/client send a message and right after that make it wait for a reply from the other, like that:
server:
while(recv(acceptedSocket,buffer,255,0)){ //here you read a message
std::cout << "clients message: " << buffer << std::endl; //print it on screen
memset(buffer,0,sizeof(buffer));
/*
instead of sending "message recieved" to server, try to get
some message from the user using cin maybe
and send() what the user has entered
then loop over and get another message
*/
std::cin.getline(buffer,255); //get user's message
//don't forget to find out buffer length
n = send(acceptedSocket, buffer, buffer_len , 0); //send the message
if(n < 0)
error("Failed sending data!");
//client has got the message now, you loop and wait for his reply
}
client:
do{
memset(buffer,0,sizeof(buffer));
std::cout << "Enter your message: " << std::endl;
std::cin.getline(buffer,255); //get message
n = send(connectingSocket,buffer,strlen(buffer),0); //send it to server
/*
recv() from the connecting socket and print the message
when you loop over, the server has your message, user enters
another one, and the client waits for the message, and then
sends something the user entered
*/
recv(connectingSocket,buffer,255,0); //wait for server's user reply
std::cout << "server's message: " << buffer << std::endl;
//you have now recieved server's message, you loop over and you're ready to send his another one
} while(n > 0);
So like this, you have to wait for a reply, you cannot send 2(+) messages i a row.
I have not tested this, but it's a rough idea of what it might look like :)
I did two different programs and it works on same computer or different ones on the network...
Have fun... this is what I started with... looking at yours, there are a number of concerns... so cut and past and play with this server and client.
//Echo Server and Client using Berkley Socket Primitives
// Server
#include <sys/socket.h>
#include <netinet/in.h>
int main (int argc, const char * argv[]) {
char buffer[128];
int sinlen;
struct sockaddr_in sin;
int s, h;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(888); // Port 888
// SOCK_STREAM is TCP
s = socket(AF_INET, SOCK_STREAM,0);
// Bind socket to local port
bind(s,(struct sockaddr*)&sin,sizeof(sin));
// Listen for 1 connection
listen(s,1);
sinlen = sizeof(sin);
// 1. Block for connection
h=accept(s,(struct sockaddr*)&sin,&sinlen );
// 2. Block for receive
recv(h,buffer,sizeof(buffer),0);
// 3. Echo received data
send(h,buffer,strlen(buffer),0);
close(h);
return 0;
}
// Client
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int main (int argc, const char * argv[]) {
char buffer[128]= "Hello world";
struct sockaddr_in sin;
struct hostent *host;
int s;
host = gethostbyname("localhost");
memcpy(&(sin.sin_addr), host->h_addr,host->h_length);
sin.sin_family = host->h_addrtype;
sin.sin_port = htons(888);
// Create socket port 888
s = socket(AF_INET, SOCK_STREAM,0);
// 1. Block for server accept
connect(s, (struct sockaddr*)&sin,sizeof(sin));
// 2. Send "Hello world"
send(s,buffer,strlen(buffer)+1,0);
// 3. Block for receive
recv(s,buffer,sizeof(buffer),0);
// Print received data
NSLog(#"Received %s\n",buffer);
close(s);
return 0;
}
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.
My aim is to write C++ program which receives data from network using udp protocol. OS - linux. I have few questions.
I want to make sure that I can use linux C libraries to write C++ program.
Is anywhere exists full tutorial which expailns step by step how to program using sockets in linux? ( I know that in network is many tutorials, but I'm looking for something which help me receive udp data from INTERNET, not from another program on the same device.).
I see in terminal ( using tcpdump) that my computer receive udp packages addressed to specified port. What's wrong with my program which looks like this
class Connection
{
private:
char * buffer;
int bufferSize;
int sock;
struct sockaddr_in server;
struct sockaddr_in other;
socklen_t addressLength;
public:
Connection(string address, int port, int bufferSize);
~Connection();
int reciveData();
};
Connection::Connection(string address, int port, int bufferSize)
{
this->addressLength = sizeof(this->server);
this->sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(this->sock == -1)
{
cout << "Socket error!" << endl;
exit(1);
}
memset(&(this->server), 0, sizeof(this->server));
this->server.sin_family = AF_INET;
this->server.sin_port = htons(port);
this->server.sin_addr.s_addr = htonl(INADDR_ANY);
if( bind(this->sock, (sockaddr *) &(this->server), this->addressLength) == -1 )
{
cout << "Bind socket error!" << endl;
exit(1);
}
this->bufferSize = bufferSize;
this->buffer = new char[bufferSize];
cout << "Socket created!" << endl;
}
int Connection::receiveData()
{
int returned;
fflush(stdout);
if( (returned =recvfrom(this->sock, this->buffer, this->bufferSize, 0, (sockaddr *) &(this->other), &this->addressLength)) == -1)
{
cout << "Receiving error!" << endl;
exit(1);
}
return returned;
}
When i call receiveData() nothing's happening - I think program waits for some udp package ( and i don't know why he does not receive it).
Could someone explain me difference between udp server and client program ?
Thanks a lot.
When calling recvfrom(), you are passing it a pointer to this->addressLength. On input, the length needs to be the complete size of the address buffer. On output, the actual address length is returned. So recvfrom() might be altering your addressLength member, affecting subsequent code. Use a local variable instead:
int Connection::receiveData()
{
int returned;
int addrlen = sizeof(this->other);
fflush(stdout);
returned = recvfrom(this->sock, this->buffer, this->bufferSize, 0, (sockaddr *) &(this->other), &addrLen);
if( returned == -1 )
{
cout << "Receiving error!" << endl;
exit(1);
}
return returned;
}
Alternatively, use a separate member variable instead:
class Connection
{
private:
char * buffer;
int bufferSize;
int sock;
struct sockaddr_in server;
struct sockaddr_in other;
socklen_t serverAddressLength;
socklen_t otherAddressLength;
public:
Connection(string address, int port, int bufferSize);
~Connection();
int reciveData();
};
Connection::Connection(string address, int port, int bufferSize)
{
this->serverAddressLength = sizeof(this->server);
this->sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(this->sock == -1)
{
cout << "Socket error!" << endl;
exit(1);
}
if(this->sock == -1)
{
cout << "Socket error!" << endl;
exit(1);
}
memset(&(this->server), 0, sizeof(this->server));
this->server.sin_family = AF_INET;
this->server.sin_port = htons(port);
this->server.sin_addr.s_addr = htonl(INADDR_ANY);
if( bind(this->sock, (sockaddr *) &(this->server), this->serverAddressLength) == -1 )
{
cout << "Bind socket error!" << endl;
exit(1);
}
this->bufferSize = bufferSize;
this->buffer = new char[bufferSize];
cout << "Socket created!" << endl;
}
int Connection::receiveData()
{
int returned;
fflush(stdout);
this->otherAddressLength = sizeof(this->other);
if( (returned =recvfrom(this->sock, this->buffer, this->bufferSize, 0, (sockaddr *) &(this->other), &this->otherAddressLength)) == -1)
{
cout << "Receiving error!" << endl;
exit(1);
}
return returned;
}
I'm making a server, client app in c++ console based.
What I did so far:
I can connect to the server.
I can send messages to the server.
The server can send the messages back.
But what I can't figure out, how can I let the server act also as a client to send messages to the client while he is processing received messages from the client?
People can use it as an example as well :D
Well I will post also some parts of the code:
server:
#include "stdafx.h"
using namespace std;
//our main function
void main()
{
int numClients;
long antwoord;
char chatname[100];
char bericht[250]; //messages
char sbericht[250]; //smessages
//here we set the Winsock-DLL to start
WSAData wsaData;
WORD DLLVERSION;
DLLVERSION = MAKEWORD(2,1);
//here the Winsock-DLL will be started with WSAStartup
//version of the DLL
antwoord = WSAStartup(DLLVERSION, &wsaData);
if(antwoord != 0)
{
WSACleanup();
exit(1);
}
else
{
cout << "WSA started successfully" <<endl;
cout << "The status: \n" << wsaData.szSystemStatus <<endl;
}
//the DLL is started
//structure of our socket is being created
SOCKADDR_IN addr;
//addr is our struct
int addrlen = sizeof(addr);
//socket sListen - will listen to incoming connections
SOCKET sListen;
//socket sConnect - will be operating if a connection is found.
SOCKET sConnect;
//setup of our sockets
//opgezocht op internet - AF_INET bekend dat het lid is van de internet familie
//Sock_STREAM betekenend dat onze socket een verbinding georiƫnteerde socket is.
sConnect = socket(AF_INET,SOCK_STREAM,NULL);
//now we have setup our struct
//inet_addr is our IP adres of our socket(it will be the localhost ip
//that will be 127.0.0.1
addr.sin_addr.s_addr = inet_addr("192.168.1.103");
//retype of the family
addr.sin_family = AF_INET;
//now the server has the ip(127.0.0.1)
//and the port number (4444)
addr.sin_port = htons(4444);
//here we will define the setup for the sListen-socket
sListen = socket(AF_INET,SOCK_STREAM,NULL);
if (sConnect == INVALID_SOCKET)
{
cout << "Error at socket(): \n" << WSAGetLastError() <<endl;
WSACleanup();
}
else
{
cout << "Connect socket() is OK!" <<endl;
}
if(sListen == INVALID_SOCKET)
{
cout << "Error at socket(): \n" << WSAGetLastError() <<endl;
WSACleanup();
}
else
{
cout << "Listen socket() is OK!" <<endl;
}
//here the sListen-socket will be bind
//we say that the socket has the IP adress of (127.0.0.1) and is on port (4444)
//we let the socket become the struct "addr"
if(bind(sListen, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
cout << "bind() failed: \n" << WSAGetLastError() <<endl;
WSACleanup();
exit(1);
}
else{
cout << "bind() is OK!" <<endl;
}
//here we will tell what the server must do when a connection is found
//therefor we will create an endless loop
cout << "Waiting for a incoming connection..." <<endl;
for(;;)
{
//now we let the socket listen for incoming connections
//SOMAXCOMM heeft het nut dat het dan voordurend luisterd naar inkomende verbindingen zonder limiet
listen(sListen, SOMAXCONN);
while(numClients < SOMAXCONN)
{
//if a connection is found: show the message!
if(sConnect = accept(sListen, (SOCKADDR*)&addr, &addrlen))
{
cout << "A Connection was found!" <<endl;
antwoord = send(sConnect, "Welcome to our chat:", 21,NULL);
if(antwoord > 1)
{
antwoord = recv(sConnect, sbericht, sizeof(sbericht), NULL);
antwoord = recv(sConnect, chatname, sizeof(chatname), NULL);
while(antwoord = recv(sConnect, sbericht, sizeof(sbericht), NULL) && (antwoord = recv(sConnect, sbericht, sizeof(sbericht), NULL)) )
{
antwoord = send(sConnect, sbericht, sizeof(sbericht), NULL);
antwoord = send(sConnect, chatname, sizeof(chatname), NULL);
}
}
else
{
cout << "The connection to the client has been lost... \n" << "please exit the server." <<endl;
break;
}
numClients++;
}
}
}
}
Client:
// ChatServer.cpp : Defines the entry point for the console application.
//
//include of the stdafx.h file where importent files are being included
#include "stdafx.h"
using namespace std;
void smessage()
{
}
//our main function
int main()
{
//here we set the Winsock-DLL to start
string bevestiging;
char chatname[100];
char bericht[250];
char sbericht[250];
string strbericht;
string strsbericht;
long antwoord;
//here the Winsock-DLL will be started with WSAStartup
//version of the DLL
WSAData wsaData;
WORD DLLVERSION;
DLLVERSION = MAKEWORD(2,1);
antwoord = WSAStartup(DLLVERSION, &wsaData);
if(antwoord != 0)
{
exit(1);
}
else
{
cout << "WSA started successfully" <<endl;
cout << "The status: \n" << wsaData.szSystemStatus <<endl;
}
SOCKADDR_IN addr;
int addrlen = sizeof(addr);
SOCKET sConnect;
sConnect = socket(AF_INET, SOCK_STREAM, NULL);
if (sConnect == INVALID_SOCKET)
{
cout << "Error at socket(): \n" << WSAGetLastError() <<endl;
}
else
{
cout << "socket() is OK!\n" <<endl;
}
addr.sin_addr.s_addr = inet_addr("192.168.1.103");
addr.sin_family = AF_INET;
addr.sin_port = htons(4444);
cout << "What is your chat name?" <<endl;
cin.getline(chatname, 100);
cout << "Do you want to connect to the server? [Y/N]" <<endl;
cin >> bevestiging;
if (bevestiging == "N")
{
exit(1);
}
else
{
if(bevestiging == "Y")
{
connect(sConnect, (SOCKADDR*)&addr, sizeof(addr));
antwoord = recv(sConnect, bericht, sizeof(bericht), NULL);
strbericht = bericht;
cout << strbericht << chatname <<endl;
while(true)
{
if(antwoord > 1)
{
cin.clear();
cin.sync();
cout << chatname << " :" <<endl;
cin.getline(sbericht, 250);
antwoord = send(sConnect, sbericht, sizeof(sbericht), NULL);
antwoord = send(sConnect, chatname, sizeof(chatname), NULL);
while(antwoord = send(sConnect, sbericht, sizeof(sbericht), NULL) && (antwoord = send(sConnect, sbericht, sizeof(sbericht), NULL)))
{
antwoord = recv(sConnect, sbericht, sizeof(sbericht), NULL);
antwoord = recv(sConnect, chatname, sizeof(chatname), NULL);
cout << chatname << ":" <<endl;
cout << sbericht <<endl;
cin.getline(sbericht, 250);
}
}
else
{
cout << "The connection to the server has been lost... \n" << "please exit the client." <<endl;
}
}
}
}
}
You would probably have to open another socket. The client would have to act as a server as well.
First of all: putting a 20mb zip file in to the web for about 4 interesting source files is not a good option. Your object files and debug output is of no interest to us, since we want to help with your source code. Try uploading a zip file containing only the source files the next time.
Secondly: If others want to understand your source code and are not familiar with your native language, they have to guess. Try using english as source code language for this and a variety of other reasons.
Now to answer your question:
The answer is already in your code. Currently, the server is looping until a maximum number of connects, receives input and sends back an answer. So actually you have already implemented it. I guess if you want to send initiated messages in both ways you have to alter your software architecture a bit.
Your code has a few fundamental problems:
The server can only handle one client at a time. If your server will ever have more than a single user on it (as a chat server invariably will), you need to be able to listen for more than one connection at once. select, or WSAEventSelect and WaitForMultipleObjects, would help a lot here.
You assume that a whole fixed-size message will appear at a time. TCP can not guarantee that (as the "stream" concept considers the data as just a potentially infinite sequence of individual bytes), and a half-sent message could freeze up your server while it waits for the rest. Not a big deal if this is all on your LAN, but if you expose this service to the internet, you're asking for random lockups. In order to prevent that, get the data and put it in a buffer as it comes, processing it only when you have a whole message.
The conversation is done in lock-step. That is, the client sends a message, and waits for a response, and then (and only then) expects console input. With this design, there will always be one message received per message sent. In order to get around this, i'll often have a thread for the data going in each direction -- one that gets the console input and sends it to the server, while the other listens to the server and prints the message received. (Note, this means messages could be received while you're typing. That's kinda the point. But it makes console input a bit annoying.) Threading is a semi-advanced topic -- once you start creating new threads, you often have to worry about synchronization and such. But it's generally cleaner than the alternatives in this case.
Sample threaded code (very roughly, since i don't have a C++ compiler handy):
const int MessageLength = 250;
const int NameLength = 250;
char myname[NameLength];
bool sendFully(SOCKET s, char* buffer, size_t buffer_len, int flags)
{
char *end = buffer + buffer_len;
while (buffer != buffer_len)
{
int sent = send(s, buffer, end - buffer, flags);
if (sent == 0) return false;
buffer += sent;
}
return true;
}
DWORD WINAPI watchConsoleInput(void*)
{
char input[MessageLength];
while (true)
{
std::cin.getline(input, MessageLength);
if (!sendFully(sConnect, input, sizeof(input), 0))
break;
if (!sendFully(sConnect, myname, sizeof(myname), 0))
break;
}
return 0;
}
int main()
{
char chatname[NameLength];
char sbericht[MessageLength];
... get our name in myname ...
... do the connect stuff ...
HANDLE watcher = CreateThread(NULL, 0, watchConsoleInput, NULL, 0, NULL);
while (true)
{
// Added MSG_WAITALL to work around the whole-message-at-a-time thing
if (recv(sConnect, sbericht, sizeof(sbericht), MSG_WAITALL) != sizeof(sbericht))
break;
if (recv(sConnect, chatname, sizeof(chatname), MSG_WAITALL) != sizeof(sbericht))
break;
}
// Don't care about errors; we're just being polite
shutdown(sConnect, SD_BOTH);
closesocket(sConnect);
cout << "Connection lost\n";
// ExitProcess rather than just 'return', so we know the watcher thread dies
ExitProcess(0);
}