I create a C++ client that connect to a C++ server.
It connect and send correctly data to a server.
I create a separate thread to receive data from the server , and here is the problem that I can't figure it out.
I get this error:
WSAGetLastError 10038
I find that this error because the descriptor is not a socket.
The server send method work correcty, I test it with a telnet client.
This is my client code:
#include <winsock2.h>
#include <windows.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <conio.h>
#include<iostream>
using namespace std;
int hsock;
void *SocketHandler(void*);
int main(int argv, char** argc){
//The port and address you want to connect to
int host_port= 2000;//1101;
char* host_name="10.188.126.198";
pthread_t recept;
//Initialize socket support WINDOWS ONLY!
unsigned short wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 || ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )) {
fprintf(stderr, "Could not find useable sock dll %d\n",WSAGetLastError());
return 0;
}
//Initialize sockets and set any options
int * p_int ;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if(hsock == -1){
printf("Error initializing socket %d\n",WSAGetLastError());
return 0;
}
p_int = (int*)malloc(sizeof(int));
*p_int = 1;
if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
(setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
printf("Error setting options %d\n", WSAGetLastError());
free(p_int);
return 0;
}
free(p_int);
//Connect to the server
struct sockaddr_in my_addr;
my_addr.sin_family = AF_INET ;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = inet_addr(host_name);
int *csock ;
csock = (int*)malloc(sizeof(int));
if( (*csock =connect( hsock, (struct sockaddr*)&my_addr, sizeof(my_addr))) == SOCKET_ERROR ){
fprintf(stderr, "Error connecting socket %d\n", WSAGetLastError());
return 0;
}
cout<<"Client connect to :"<< htons(host_port)<<endl;
//Create thread to receive data from the server
// the problem is here as I think
pthread_create(&recept,NULL,SocketHandler,(void *)csock);
/// Send data to the server
char buffer[1024];
int buffer_len = 1024;
int bytecount;
int c;
while(true){
memset(buffer, '\0', buffer_len);
for(char* p=buffer ; (c=getch())!=13 ; p++){
printf("%c", c);
*p = c;
}
if( (bytecount=send(hsock, buffer, strlen(buffer),0))==SOCKET_ERROR){
fprintf(stderr, "Error sending data %d\n", WSAGetLastError());
return 0;
}
printf("Sent bytes %d\n", bytecount);
}
closesocket(hsock);
return 0;
}
void *SocketHandler(void* lp){
int *csock= (int*)lp;
cout<<"Start Listening Thread"<<endl;
char buffer[1024];
int buffer_len = 1024;
int bytecount;
memset(buffer, 0, buffer_len);
while(1){
memset(buffer, 0, buffer_len);
if((bytecount = recv(*csock, buffer, buffer_len, 0))==SOCKET_ERROR){
fprintf(stderr, "Error receiving data %d\n", WSAGetLastError());
break;
}
printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer);
}
free(csock);
return 0;
}
Function 'connect' returns result, not socket handle (https://msdn.microsoft.com/en-us/library/windows/desktop/ms737625%28v=vs.85%29.aspx). Change it to:
...
if (connect(hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == SOCKET_ERROR) {
fprintf(stderr, "Error connecting socket %d\n", WSAGetLastError());
return 0;
}
*csock = hsock;
...
The parameter that you send to the thread is the csock...
int *csock ;
csock = (int*)malloc(sizeof(int));
...
pthread_create(&recept,NULL,SocketHandler,(void *)csock);
and then you use the csock as a the socket (in the thread)...
int *csock= (int*)lp;
...
if((bytecount = recv(*csock, buffer, buffer_len, 0))==SOCKET_ERROR) {
I think that you need to use the hsock as your socket and not the *csock...
BTW:
In windows you should call it a SOCKET and not int...
Hope it helps...
Related
Following is a single server-client code which are trying to send-receive few buffers, and later close the connection.
Server Code:
#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 <arpa/telnet.h>
#include <unistd.h>
char buff1[][3]= {{0xff , 0xfd, 0x18},{0xff , 0xfd, 0x1e},{0xff , 0xfd, 0x1d}};
char recbuf[1024];
void mwrite (int sock, char * buf, int size)
{
int n = send( sock, buf, size, 0 );
if (n < 0)
{
perror("ERROR writing to socket");
return;
}
}
void read (int sock)
{
char buffer[256];
/* Now read client response */
memset(buffer, 0, sizeof(buffer));
int n = recv( sock, buffer, 255, 0 );
if (n < 0)
{
perror("ERROR reading from socket");
return;
}
for (int i = 0; i < n; i++)
printf("%2x ", buffer[i]);//printing ascii characters
printf("\n");
}
int main(int argc , char *argv[] )
{
int sockfd , newsockfd , portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
sockfd = socket(AF_INET , SOCK_STREAM , 0);
if (sockfd < 0 )
{
perror("Error opening socket ");
exit(1);
}
/* Initialize socket structure */
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);
/* Now bind the host address using client */
if(bind(sockfd, (struct sockaddr *) &serv_addr , sizeof(serv_addr)) <0)
{
perror("Error on binding");
exit(1);
}
if(listen(sockfd,5)<0)
{
perror("Error on listen");
exit(1);
}
int count = 1;
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
{
perror("ERROR on accept");
exit(1);
}
printf("Server Sending (DO TERMINAL TYPE)\n");
while ((n = write(newsockfd,buff1,sizeof(buff1)))>0)
{
printf("Server Sent query %d: %x %x %x\n", count, buff1[count][0], buff1[count][1], buff1[count][2]);
n = read(newsockfd, recbuf , sizeof(recbuf));
printf("Server received responset: %x %x %x\n", recbuf[0], recbuf[1], recbuf[2]);
count++;
count = count % 3;
if(n<0)
{
perror("Error writing to socket ");
exit(1);
}
}
return 0 ;
}
Client Code :
#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 <arpa/telnet.h>
#include <unistd.h>
#include <netdb.h>
char buff2[] = {0xff,0xfc,0x18};
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("\n%d bytes received buffer is: %s", n, buffer);
}
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 *server1;
char buffer1[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);
}
server1 = gethostbyname(argv[1]);
if (server1 == NULL)
{
fprintf(stderr,"ERROR no such host \n");
exit(0);
}
bzero((char *) &serv_addr , sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server1->h_addr, (char*)&serv_addr.sin_addr.s_addr, server1->h_length);
serv_addr.sin_port = htons( portno );
/*Connect to server*/
if (connect( sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr) ) < 0)
{
perror("ERROR connecting");
return(1);
}
printf("Recieving Buffer 1 from Server side");
bzero(buffer1,256);
while(true)
{
n= read(sockfd,buffer1,sizeof(buffer1));
if(n<0)
printf("ERROR reading in socket %d len %d", n, sizeof(buffer1));
n= write(sockfd,buff2,sizeof(buff2));
if(n<0)
printf("ERROR writing in socket %d len %d", n, sizeof(buff2));
printf("\nSent Buffer2 (WON'T TERMINAL TYPE) from client side");
}
return 0;
}
Output :
Server Side :
./single_sample 5667
Server Sending (DO TERMINAL TYPE)
Server Sent query 1: ffffffff fffffffd 1e
Server received responset: ffffffff fffffffc 18
Server Sent query 2: ffffffff fffffffd 1d
Server received responset: ffffffff fffffffc 18
Error writing to socket : Connection reset by peer
Client Side:
./sample_client 127.0.0.1 5667
Recieving Buffer 1 from Server side
Sent Buffer2 (WON'T TERMINAL TYPE) from client side
Basically I am trying to close the socket once both the buffers are sent. But getting the above error. I am unable to solve whether the error is occuring from server side or client side.
Also, while running this code on a linux machine how to capture the data bytes sent on wireshark
Thanks in advance.
Your client writes its message and then immediately disconnects, which leads the server to get the Connection reset by peer error - since the client part of the connection no longer exists.
I am trying to implement Socket where client send sentence to server and server replies back two integer valeus pcount and ncount. I can receive both this but first recv operation receives both values and also appends some other data to buffer.
Client.cpp
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <netinet/in.h>
#include <resolv.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
char *foo(char* buf)
{
char buffer[1024];
char *a='\0';
char *c=buf;
strcpy(buffer,buf);
int host_port= 1102;
char* host_name="127.0.0.1";
struct sockaddr_in my_addr;
//char buffer[1024];
int bytecount;
int buffer_len=0;
int hsock;
int * p_int;
int err;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if(hsock == -1){
printf("Error initializing socket %d\n",errno);
goto FINISH;
}
p_int = (int*)malloc(sizeof(int));
*p_int = 1;
if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
(setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
printf("Error setting options %d\n",errno);
free(p_int);
goto FINISH;
}
free(p_int);
my_addr.sin_family = AF_INET ;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = inet_addr(host_name);
if( connect( hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1 ){
if((err = errno) != EINPROGRESS){
fprintf(stderr, "Error connecting socket %d\n", errno);
goto FINISH;
}
}
//Now lets do the client related stuff
buffer_len = 1024;
memset(buf, '\0', buffer_len);
buf[strlen(buf)-1]='\0';
if( (bytecount=send(hsock, buffer, strlen(buffer),0))== -1){
fprintf(stderr, "Error sending data %d\n", errno);
go
to FINISH;
}
printf("Sent bytes %d\n", bytecount);
//-------
// may Needs to empty content of buffer here but dont know how to do. Tried with fflush, free(buffer) but does not work
//Two recv function which ideally recv pcount and ncount subsequently
if((bytecount = recv(hsock, buffer, buffer_len, 0))== -1){
fprintf(stderr, "Error receiving data %d\n", errno);
goto FINISH;
}
printf("Recieved bytes %d\nReceived string \"%s \n", bytecount, buffer);
//Needs to empty content of buffer here but dont know how to do. Tried with fflush, free(buffer) but does not work
if((bytecount = recv(hsock, buffer, buffer_len, 0))== -1){
fprintf(stderr, "Error receiving data %d\n", errno);
goto FINISH;
}
printf("Recieved bytes %d\nReceived string \"%s \n", bytecount, buffer);
close(hsock);
FINISH:
;
return buffer;
}
And server.cpp :
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <netinet/in.h>
#include <resolv.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
//#include <errno.h>
#include <stdio.h>
#include <netinet/in.h>
#include <resolv.h>
#include <sys/socket.h>
#include <unistd.h>
//#include <sstream.h>
#include <pthread.h>
#include "serverFunction.cpp"
#include "serverFunction2.cpp"
#include <iostream>
#include <sstream>
#include <cstdio>
using namespace std;
void *SocketHandler(void *);
int main(int argv, char **argc)
{
int host_port = 1102;
char buf[20];
int k;
struct sockaddr_in my_addr;
int hsock;
int *p_int;
int err;
socklen_t addr_size = 0;
int *csock;
sockaddr_in sadr;
pthread_t thread_id = 0;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if (hsock == -1) {
printf("Error initializing socket %dn", errno);
goto FINISH;
}
p_int = (int *) malloc(sizeof(int));
*p_int = 1;
if ((setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char *) p_int, sizeof(int)) == -1) || (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char *) p_int, sizeof(int)) == -1)) {
printf("Error setting options %dn", errno);
free(p_int);
goto FINISH;
}
free(p_int);
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(hsock, (sockaddr *) & my_addr, sizeof(my_addr)) == -1) {
fprintf(stderr, "Error binding to socket, make sure nothing else is listening on this port %dn", errno);
goto FINISH;
}
if (listen(hsock, 10) == -1) {
fprintf(stderr, "Error listening %dn", errno);
goto FINISH;
}
//Now lets do the server stuff
addr_size = sizeof(sockaddr_in);
while (true) {
printf("waiting for a connectionn\n");
csock = (int *) malloc(sizeof(int));
if ((*csock = accept(hsock, (sockaddr *) & sadr, &addr_size)) != -1) {
printf("---------------------nReceived connection from %s\n", inet_ntoa(sadr.sin_addr));
pthread_create(&thread_id, 0, &SocketHandler, (void *) csock);
pthread_detach(thread_id);
} else {
fprintf(stderr, "Error accepting %dn", errno);
}
}
FINISH:
;
}
void *SocketHandler(void *lp)
{
int result=0;
//std::stringstream ss;
int *csock = (int *) lp;
char buf[20];
int k;
// char *target="my name is khan";
char *str;
char *str2;
int pcount = 0, ncount = 0;
char buffer[1024];
int buffer_len = 1024;
int bytecount;
int i = 0,t=0,q=0;
int j = 0;
char *ch[50] = { 0 }; /* stores references to 50 words. */
char *ch2[50] = { 0 };
char *word = strtok(buffer, " ");
char *word2 = strtok(buffer, " ");
char *portstring1=(char *)malloc(sizeof(buffer));
char *portstring2=(char *)malloc(sizeof(buffer));
memset(buffer, 0, buffer_len);
if ((bytecount = recv(*csock, buffer, buffer_len, 0)) == -1) {
fprintf(stderr, "Error receiving data %d \n", errno);
goto FINISH;
}
printf("Received bytes %d \n Received string %s \n ", bytecount, buffer);
/* stores references to 50 words. */
word = strtok(buffer, " ");
while ((NULL != word) && (50 > i)) {
ch[i] = strdup(word);
//printf("%s n", ch[i]);
str = BoyerMoore_positive(ch[i], strlen(ch[i]) - 1);
str2= BoyerMoore_negative(ch[i], strlen(ch[i]) - 1);
if (str == NULL)
t++;
else {
printf("%s \n", ch[i]);
// puts("true");
pcount += 1;
printf("Positive count is: %d \n",pcount);
}
if(str2== NULL)
q++;
else {
printf("%s \n", ch[i]);
// puts("true");
ncount += 1;
printf("Nagative count is: %d \n",ncount);
}
i++;
word = strtok(NULL, " ");
}
//I want to send pcount and ncount values to client
**sprintf(portstring1, "%d", pcount);
if ((bytecount = send(*csock, portstring1, 1, 0)) == -1) {
fprintf(stderr, "Error sending data %d\n", errno);
goto FINISH;
}
sprintf(portstring2, "%d", ncount);
if ((bytecount = send(*csock, portstring2, strlen(portstring2), 0)) == -1) {
fprintf(stderr, "Error sending data %d\n", errno);
goto FINISH;
}**
FINISH:
free(csock);
return 0;
}
I receive output like this:
Enter sentence to send to the server (press enter)
critic worst nice
Sent bytes 18
Recieved bytes 2
Received string 12itic worst nice //Here there should be only 1 2. Why 'itic ..' gets appended. And why 1 and 2 both does not get printed one after another
You forgot to design and implement a protocol. Network communication doesn't work by magic. If you have a notion of an application-level message, you have to write code to send and receive application-level messages. You haven't done this, so of course it won't happen.
Also:
printf("Received bytes %d \n Received string %s \n ", bytecount, buffer);
The %s format specifier is only for C-style strings. It's not suitable for arbitrary data. How would it know how many bytes to print?
The recv function does not add a nul character to terminate the received string. You have to add it yourself, like this:
if((bytecount = recv(hsock, buffer, buffer_len-1, 0))== -1){
fprintf(stderr, "Error receiving data %d\n", errno);
goto FINISH;
}
buffer[bytecount]=0;
Notice the -1 in buffer len, to make sure there's room for the nul character.
#Joni and David- Thanks for your support!
Problem solved:
at sender:
int ar[2];
if ((bytecount = send(*csock, (char *)ar, 2 *sizeof(int), 0)) == -1) { // Here we cant send lenth-1. It consider exact
fprintf(stderr, "Error sending data %d\n", errno);
goto FINISH;
}
at receiver side:
if((bytecount = recv(hsock, ar, 2 * sizeof(int), 0))== -1){
fprintf(stderr, "Error receiving data %d\n", errno);
goto FINISH;
}
for(k=0;k<2;k++)
{
printf("count is :%d",ar[k]);
}
just took and array, Now I can send any receive any numbers of values! It's so easy!
Communication between a server and a clients works, but the server don't forward the client messages to the other connected client's, but only to the sender.
i want the server react to incoming messages by broadcasting them to all clients like a chat system, but keep my command system without sharring it with all clients, but with with sender.
down below is the sources:
server
/*server*/
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <string>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <process.h>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define PORT "3490"
#define SERVER "localhost"
#include <time.h>
WSADATA wsa;
SOCKET s , new_socket;
struct sockaddr_in server , client;
int c;
char *message;
std::string line;
DWORD WINAPI ProcessClient (LPVOID lpParameter)
{
SOCKET AcceptSocket = (SOCKET) lpParameter;
// Send and receive data.
int bytesSent;
int bytesRecv = SOCKET_ERROR;
char sendbuf[2000]="";
char sendbuf2[2000]="";
char recvbuf[2000]="";
char timebuf[128];
sprintf(sendbuf, "Hello, it's a test server at %s:%d (commands: 1, 2, exit)\n", SERVER, PORT);
bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
if (bytesSent == SOCKET_ERROR)
{
printf( "Error at send hello: %ld\n", WSAGetLastError());
goto fin;
}
while (1)
{
_strtime( timebuf );
ZeroMemory (recvbuf, sizeof(recvbuf));
bytesRecv = recv( AcceptSocket, recvbuf, 32, 0);
printf( "%s Client said: %s\n", timebuf, recvbuf);
sprintf(sendbuf, "%s Client said: %s\n", timebuf, recvbuf);
bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
if (strcmp(recvbuf, "1") == 0)
{
sprintf(sendbuf, "You typed ONE\n");
//printf("Sent '%s'\n", sendbuf);
bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
if (bytesSent == SOCKET_ERROR)
{
printf( "Error at send: %ld\n", WSAGetLastError());
goto fin;
}
}
else if (strcmp(recvbuf, "2") == 0)
{
sprintf(sendbuf, "You typed TWO\n");
//printf("Sent '%s'\n", sendbuf);
bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
if (bytesSent == SOCKET_ERROR)
{
printf( "Error at send: %ld\n", WSAGetLastError());
goto fin;
}
}
else if (strcmp(recvbuf, "exit") == 0)
{
printf( "Client has logged out\n", WSAGetLastError());
goto fin;
}
else
{
// sprintf(sendbuf, "unknown command\n");
//printf("Sent '%s'\n", sendbuf);
// bytesSent = send( AcceptSocket, sendbuf, strlen(sendbuf), 0);
if (bytesSent == SOCKET_ERROR)
{
// printf( "Error at send: %ld\n", WSAGetLastError());
goto fin;
}
}
}
fin:
printf("Client processed\n");
closesocket(AcceptSocket);
return 0;
}
int main(int argc , char *argv[])
{
std::cout << ("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
std::cout << ("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
std::cout << ("Could not create socket : %d" , WSAGetLastError());
}
std::cout << ("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 3490 );
//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
std::cout << ("Bind failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
//Listen to incoming connections
listen(s , 3);
//Accept and incoming connection
std::cout << ("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while(true){
while((new_socket = accept(s , (struct sockaddr *)&client, &c)) != INVALID_SOCKET) {
// Create a new thread for the accepted client (also pass the accepted client socket).
printf( "Client Connected.\n");
DWORD dwThreadId;
CreateThread (NULL, 0, ProcessClient, (LPVOID) new_socket, 0, &dwThreadId);
}
}
if (new_socket == INVALID_SOCKET)
{
std::cout << ("accept failed with error code : %d" , WSAGetLastError());
return 1;
}
closesocket(s);
WSACleanup();
return 0;
}
client
/*client*/
#define WIN32_LEAN_AND_MEAN
#pragma comment(lib,"ws2_32.lib")
#include <iostream>
#include <process.h>
#include <string>
#include <winsock2.h>
SOCKET Socket;
#define SERVER "localhost"
int PORT = 3490;
std::string line;
bool chat = false;
class Buffer
{
public:
int ID;
char Message[256];
}sbuffer;
int ClientThread()
{
char buffer[2000]= "";
for(;; Sleep(10))
{
if(recv(Socket, buffer, sizeof(sbuffer), NULL)!=SOCKET_ERROR)
{
strncpy(sbuffer.Message, buffer, sizeof(sbuffer.Message));
std::cout << "<Client:" << sbuffer.ID << ":> " << sbuffer.Message <<std::endl;
ZeroMemory (buffer, sizeof(buffer));
}
}
return 0;
}
int main(void)
{
WSADATA WsaDat;
if(WSAStartup(MAKEWORD(2,2),&WsaDat)!=0)
{
std::cout<<"Winsock error - Winsock initialization failed\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
// Create our socket
Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(Socket==INVALID_SOCKET)
{
std::cout<<"Winsock error - Socket creation Failed!\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
// Resolve IP address for hostname
struct hostent *host;
if((host=gethostbyname(SERVER))==NULL)
{
std::cout<<"Failed to resolve hostname.\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
// Setup our socket address structure
SOCKADDR_IN SockAddr;
SockAddr.sin_port=htons(PORT);
SockAddr.sin_family=AF_INET;
SockAddr.sin_addr.s_addr=*((unsigned long*)host->h_addr);
// Attempt to connect to server
if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr))!=0)
{
std::cout<<"Failed to establish connection with server\r\n";
WSACleanup();
system("PAUSE");
return 0;
}
// If iMode!=0, non-blocking mode is enabled.
u_long iMode=1;
ioctlsocket(Socket,FIONBIO,&iMode);
// Main loop
for(;;)
{
// Display message from server
char buffer[1000];
memset(buffer,0,999);
int inDataLength=recv(Socket,buffer,1000,0);
std::cout<<buffer;
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE) ClientThread, NULL, NULL, NULL);
for(;; Sleep(10))
{
std::string buffer;
std::getline(std::cin, buffer);
if (send(Socket, buffer.c_str(), buffer.length(), NULL) < 1){
}
}
int nError=WSAGetLastError();
if(nError!=WSAEWOULDBLOCK&&nError!=0)
{
std::cout<<"Winsock error code: "<<nError<<"\r\n";
std::cout<<"Server disconnected!\r\n";
// Shutdown our socket
shutdown(Socket,SD_SEND);
// Close our socket entirely
closesocket(Socket);
break;
}
Sleep(1000);
}
WSACleanup();
system("PAUSE");
return 0;
}
Please help me fix it, i'm new into socket's. Show me how to do as i'm going understand better with code and it will also be usefull to others who might need it in the future.
If you need the server to communicate with multiple clients, then you need some kind of collection of all the connected clients. Then it's easy to send to all connections, or send to all connection but the originating connection.
How to do it will differ vastly between C and C++, but for C++ look into structures and std::vector.
In pseudo-code it would be something like this:
while (run_server)
{
poll_all_connections();
if (have_new_connection())
{
accept_new_connection();
add_connection_in_collection();
}
else
{
for (connection in all_connections())
{
if (have_input(connection))
{
input = read_from_connection(connection);
for (send_to in all_connections())
write_to_connection(connection, input)
}
}
}
}
If you implement the above pseudo-code, then input from any connection will be sent to all connections.
Don't forget to remove a connection from the collection if the connection is broken (error or disconnect.)
You have to maintain a list of all the client socket connections then send the data to each client one by one.
or you can use threading to implement this as follows :-
Server-thread()
{
while(true)
{
/// Accept Connection in ClientSocket.
HandleClient-Thread(ClientSocket) ; // launch a thread for each client .
}
}
HandleClient-Thread(ClientSocket)
{
// handle this client here
}
i'm trying make asynchronous server listener with C++ i'm new in c++ but i must do this project , i'm web developer (PHP) but PHP can't make async connections + he is very poor language for big amount of connections... i can write simple listener without asynchronous but now i have problem with "CreateThread"... for example if client has been connected console gives me result about this + sniffer can fix it... after 10 sec client must send me again same packet with different data. my console does not gives me result about that packet but sniffer can see that packet... please if anyone can see my problem explain me ... (sorry for my bad english :D )
#include <winsock2.h>
#include <windows.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
DWORD WINAPI SocketHandler(void*);
int main(int argv, char** argc){
//The port you want the server to listen on
int host_port = 7878;
//Initialize socket support WINDOWS ONLY!
unsigned short wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 || ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )) {
fprintf(stderr, "Could not find useable sock dll %d\n",WSAGetLastError());
}
//Initialize sockets and set any options
int hsock;
int * p_int ;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if(hsock == -1){
printf("Error initializing socket %d\n",WSAGetLastError());
}
p_int = (int*)malloc(sizeof(int));
*p_int = 1;
if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
(setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
printf("Error setting options %d\n", WSAGetLastError());
free(p_int);
}
free(p_int);
//Bind and listen
struct sockaddr_in my_addr;
my_addr.sin_family = AF_INET ;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = INADDR_ANY ;
if( bind( hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1 ){
fprintf(stderr,"Error binding to socket, make sure nothing else is listening on this port %d\n",WSAGetLastError());
}
if(listen( hsock, 10) == -1 ){
fprintf(stderr, "Error listening %d\n",WSAGetLastError());
}
//Now lets to the server stuff
int* csock;
sockaddr_in sadr;
int addr_size = sizeof(SOCKADDR);
while(true){
printf("waiting for a connection\n");
csock = (int*)malloc(sizeof(int));
if((*csock = accept( hsock, (SOCKADDR*)&sadr, &addr_size))!= INVALID_SOCKET ){
printf("Received connection from %s",inet_ntoa(sadr.sin_addr));
CreateThread(0,0,&SocketHandler, (void*)csock , 0,0);
}
else{
fprintf(stderr, "Error accepting %d\n",WSAGetLastError());
}
}
}
DWORD WINAPI SocketHandler(void* lp){
int *csock = (int*)lp;
char buffer[1024];
int buffer_len = 1024;
int bytecount;
memset(buffer, 0, buffer_len);
if((bytecount = recv(*csock, buffer, buffer_len, 0))==SOCKET_ERROR){
fprintf(stderr, "Error receiving data %d\n", WSAGetLastError());
}
printf("Received bytes %d\n Received string \"%s\"\n", bytecount, buffer);
char buff[1] = {0x11};
if((bytecount = send(*csock, buff, 1, 0))==SOCKET_ERROR){
fprintf(stderr, "Error sending data %d\n", WSAGetLastError());
}
printf("Sent bytes: %d. Send Message: %s\n ", bytecount,buff);
free(csock);
}
I suspect the issue not be the creating a thread, but in the passing of the data. It is probably simpler to just pass the socket to the thread. Additionally, at the end of the function you correctly free the memory, but you did not close the socket. I have made changes and verified that it functions correctly. The changes I made are comments with //*
#include <winsock2.h>
#include <windows.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
DWORD WINAPI SocketHandler(void*);
//*** Changed to work with my version of
//*** Visual Studio
int _tmain(int argc, _TCHAR* argv[]){
//The port you want the server to listen on
int host_port = 7878;
//Initialize socket support WINDOWS ONLY!
unsigned short wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 || ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )) {
fprintf(stderr, "Could not find useable sock dll %d\n",WSAGetLastError());
}
//Initialize sockets and set any options
//*** Changed to be SOCKET instead of int
SOCKET hsock;
int * p_int ;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if(hsock == -1){
printf("Error initializing socket %d\n",WSAGetLastError());
}
p_int = (int*)malloc(sizeof(int));
*p_int = 1;
if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
(setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
printf("Error setting options %d\n", WSAGetLastError());
free(p_int);
}
free(p_int);
//Bind and listen
struct sockaddr_in my_addr;
my_addr.sin_family = AF_INET ;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = INADDR_ANY ;
if( bind( hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1 ){
fprintf(stderr,"Error binding to socket, make sure nothing else is listening on this port %d\n",WSAGetLastError());
}
if(listen( hsock, 10) == -1 ){
fprintf(stderr, "Error listening %d\n",WSAGetLastError());
}
//Now lets to the server stuff
//*** Changed to be SOCKET instead of int*
SOCKET csock;
sockaddr_in sadr;
int addr_size = sizeof(SOCKADDR);
while(true){
printf("waiting for a connection\n");
//*** Changed to comment out line as it is not needed
// csock = (SOCKET)malloc(sizeof(SOCKET));
//*** Changed check to be INVALID_SOCKET
if((csock = accept( hsock, (SOCKADDR*)&sadr, &addr_size))!= INVALID_SOCKET ){
printf("Received connection from %s",inet_ntoa(sadr.sin_addr));
//*** Changed to pass the client socket
CreateThread(0,0,&SocketHandler, (void*)csock , 0,0);
}
else{
fprintf(stderr, "Error accepting %d\n",WSAGetLastError());
}
}
}
DWORD WINAPI SocketHandler(void* lp){
//** Changed to cast as the SOCKET which was passed
SOCKET csock = (SOCKET)lp;
char buffer[1024];
int buffer_len = 1024;
int bytecount;
memset(buffer, 0, buffer_len);
if((bytecount = recv(csock, buffer, buffer_len, 0))==SOCKET_ERROR){
fprintf(stderr, "Error receiving data %d\n", WSAGetLastError());
}
printf("Received bytes: %d\nReceived string: \"%s\"\n", bytecount, buffer);
char buff[1] = {0x11};
if((bytecount = send(csock, buff, 1, 0))==SOCKET_ERROR){
fprintf(stderr, "Error sending data %d\n", WSAGetLastError());
}
printf("Sent bytes: %d. Send Message: %s\n ", bytecount,buff);
//*** Changed to close the socket after the message is sent. Otherwise
//*** the socket would remain open
closesocket(csock);
//*** Changed to comment the line out as there is
//*** no allocated memory.
//free(csock);
return 0;
}
I am trying to explore Protocol Buffer (PB) in Linux platform and my coding language is C++. I found examples in the protocol buffer online docs but nothing specific to socket send and receive (Or I have missed it completely :) ). So I decided to add the message Length before the actual message and send it across socket. I would appreciate if anyone can suggest a better solution than what I am planning to do and also is there anything ready made in PB for creating such packets.
But I still end up with a problem at server side where I have to decode the packet. Say if the client sends a packet of 10 byte in which first 4 byte is the length of the packet; But it is impossible to know the length before decoding the packet. So even if i read the first 4 byte how do i deduce the the value with half read packet using Protocol Buffer.
At last I could get it working . I am posting the code here so that one can review and comment on it as well as if some one wants to implement it in c++, this piece of code can help. Its a shabby code my intention was to get Protobuf working in length prefixed manner. I have taken the code of client server from some site which I don't remember and I have modified it to accommodate protobuf. Here the server first peeks into the socket and gets the length of the total packet and then actual socket read is done to read the entire packet. There can be zillion ways to do it but for quick solution I did it in this manner. But I need to find a better way to avoid 2 recv per packets, but in my condition all the messages are of different size, so this is the only way I guess.
Proto file
message log_packet {
required fixed64 log_time =1;
required fixed32 log_micro_sec =2;
required fixed32 sequence_no =3;
required fixed32 shm_app_id =4;
required string packet_id =5;
required string log_level=6;
required string log_msg=7;
}
Protocol buffer Client Code
#include <unistd.h>
#include "message.pb.h"
#include <iostream>
#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
using namespace google::protobuf::io;
using namespace std;
int main(int argv, char** argc){
/* Coded output stram */
log_packet payload ;
payload.set_log_time(10);
payload.set_log_micro_sec(10);
payload.set_sequence_no(1);
payload.set_shm_app_id(101);
payload.set_packet_id("TST");
payload.set_log_level("DEBUG");
payload.set_log_msg("What shall we say then");
cout<<"size after serilizing is "<<payload.ByteSize()<<endl;
int siz = payload.ByteSize()+4;
char *pkt = new char [siz];
google::protobuf::io::ArrayOutputStream aos(pkt,siz);
CodedOutputStream *coded_output = new CodedOutputStream(&aos);
coded_output->WriteVarint32(payload.ByteSize());
payload.SerializeToCodedStream(coded_output);
int host_port= 1101;
char* host_name="127.0.0.1";
struct sockaddr_in my_addr;
char buffer[1024];
int bytecount;
int buffer_len=0;
int hsock;
int * p_int;
int err;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if(hsock == -1){
printf("Error initializing socket %d\n",errno);
goto FINISH;
}
p_int = (int*)malloc(sizeof(int));
*p_int = 1;
if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
(setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
printf("Error setting options %d\n",errno);
free(p_int);
goto FINISH;
}
free(p_int);
my_addr.sin_family = AF_INET ;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = inet_addr(host_name);
if( connect( hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1 ){
if((err = errno) != EINPROGRESS){
fprintf(stderr, "Error connecting socket %d\n", errno);
goto FINISH;
}
}
for (int i =0;i<10000;i++){
for (int j = 0 ;j<10;j++) {
if( (bytecount=send(hsock, (void *) pkt,siz,0))== -1 ) {
fprintf(stderr, "Error sending data %d\n", errno);
goto FINISH;
}
printf("Sent bytes %d\n", bytecount);
usleep(1);
}
}
delete pkt;
FINISH:
close(hsock);
}
Protocol buffer Server Code
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <netinet/in.h>
#include <resolv.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include "message.pb.h"
#include <iostream>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
using namespace std;
using namespace google::protobuf::io;
void* SocketHandler(void*);
int main(int argv, char** argc){
int host_port= 1101;
struct sockaddr_in my_addr;
int hsock;
int * p_int ;
int err;
socklen_t addr_size = 0;
int* csock;
sockaddr_in sadr;
pthread_t thread_id=0;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if(hsock == -1){
printf("Error initializing socket %d\n", errno);
goto FINISH;
}
p_int = (int*)malloc(sizeof(int));
*p_int = 1;
if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
(setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
printf("Error setting options %d\n", errno);
free(p_int);
goto FINISH;
}
free(p_int);
my_addr.sin_family = AF_INET ;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = INADDR_ANY ;
if( bind( hsock, (sockaddr*)&my_addr, sizeof(my_addr)) == -1 ){
fprintf(stderr,"Error binding to socket, make sure nothing else is listening on this port %d\n",errno);
goto FINISH;
}
if(listen( hsock, 10) == -1 ){
fprintf(stderr, "Error listening %d\n",errno);
goto FINISH;
}
//Now lets do the server stuff
addr_size = sizeof(sockaddr_in);
while(true){
printf("waiting for a connection\n");
csock = (int*)malloc(sizeof(int));
if((*csock = accept( hsock, (sockaddr*)&sadr, &addr_size))!= -1){
printf("---------------------\nReceived connection from %s\n",inet_ntoa(sadr.sin_addr));
pthread_create(&thread_id,0,&SocketHandler, (void*)csock );
pthread_detach(thread_id);
}
else{
fprintf(stderr, "Error accepting %d\n", errno);
}
}
FINISH:
;//oops
}
google::protobuf::uint32 readHdr(char *buf)
{
google::protobuf::uint32 size;
google::protobuf::io::ArrayInputStream ais(buf,4);
CodedInputStream coded_input(&ais);
coded_input.ReadVarint32(&size);//Decode the HDR and get the size
cout<<"size of payload is "<<size<<endl;
return size;
}
void readBody(int csock,google::protobuf::uint32 siz)
{
int bytecount;
log_packet payload;
char buffer [siz+4];//size of the payload and hdr
//Read the entire buffer including the hdr
if((bytecount = recv(csock, (void *)buffer, 4+siz, MSG_WAITALL))== -1){
fprintf(stderr, "Error receiving data %d\n", errno);
}
cout<<"Second read byte count is "<<bytecount<<endl;
//Assign ArrayInputStream with enough memory
google::protobuf::io::ArrayInputStream ais(buffer,siz+4);
CodedInputStream coded_input(&ais);
//Read an unsigned integer with Varint encoding, truncating to 32 bits.
coded_input.ReadVarint32(&siz);
//After the message's length is read, PushLimit() is used to prevent the CodedInputStream
//from reading beyond that length.Limits are used when parsing length-delimited
//embedded messages
google::protobuf::io::CodedInputStream::Limit msgLimit = coded_input.PushLimit(siz);
//De-Serialize
payload.ParseFromCodedStream(&coded_input);
//Once the embedded message has been parsed, PopLimit() is called to undo the limit
coded_input.PopLimit(msgLimit);
//Print the message
cout<<"Message is "<<payload.DebugString();
}
void* SocketHandler(void* lp){
int *csock = (int*)lp;
char buffer[4];
int bytecount=0;
string output,pl;
log_packet logp;
memset(buffer, '\0', 4);
while (1) {
//Peek into the socket and get the packet size
if((bytecount = recv(*csock,
buffer,
4, MSG_PEEK))== -1){
fprintf(stderr, "Error receiving data %d\n", errno);
}else if (bytecount == 0)
break;
cout<<"First read byte count is "<<bytecount<<endl;
readBody(*csock,readHdr(buffer));
}
FINISH:
free(csock);
return 0;
}
Unfortunately, protobuf does not provide a way for "packaging" (delimiting) your messages:
If you want to write multiple messages to a single file or stream, it
is up to you to keep track of where one message ends and the next
begins. The Protocol Buffer wire format is not self-delimiting, so
protocol buffer parsers cannot determine where a message ends on their
own. The easiest way to solve this problem is to write the size of
each message before you write the message itself.
(from their documentation)
So, they basically recommend the same solution you arrived at.