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!
Related
I'm a newbie in socket programming. I'm trying to make a server/ client program to download a file.
Firstly, i init some step that i usually do in other program for set up a connection form client to server.
Next, From server side, I'm try to in put number of bytes that send to client to set up the receive buffer's size. From client side, I receive the number in string type. I convert it to long type and set it to buffer size.
Then, From client side, I enter the name of file that need to download from server. Server receive the name and check if it exist or not.
Last step ( THE PROBLEM STEP, i think ) server try to open file. if file is opened, send the file name back to client. client check file name if it same what it sent or not.
======> my problem is file name sent back to client:
- From server side: I print it out and check. it's correct.
- From client: I print buffer out right after read from server. It's not correct. sometimes, it's empty. sometimes, it's some-random-value.
I have done exactly like previous step.
Server.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2)
{
perror("you have to input port");
exit(1);
}
// init sockfd
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("sockfd perror");
exit(1);
}
// sockopt
int opt = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
// init server
bzero(&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);
// bind port
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
perror("ERROR on binding");
exit(1);
}
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
{
perror("ERROR on accept");
exit(1);
}
char buffer[256];
// write buff size
int buffsize;
printf("Input recive buffsize in Byte: ");
scanf("%d", &buffsize);
if (buffsize <= 0)
{
perror("Buffer size must be > 0");
exit(1);
}
bzero(buffer, sizeof(buffer));
bcopy(to_string(buffsize).c_str(), buffer, sizeof(buffer));
n = write(newsockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("fail to send buffer size");
exit(0);
}
//read file name
bzero(buffer, sizeof(buffer));
n = read(newsockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("ERROR reading from socket");
exit(1);
}
// open file:
char filename[strlen(buffer) + 1];
bcopy(buffer, filename, sizeof(filename));
FILE *pf;
unsigned long fsize;
pf = fopen(filename, "rb");
if (pf == NULL)
{
bzero(buffer, sizeof(buffer));
bcopy("File not found", buffer, sizeof(buffer));
n = write(newsockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("ERROR writing to socket");
exit(1);
}
printf("File not found!\n");
return 1;
}
else
{
printf("File %s is openned \n", filename);
fseek(pf, 0, SEEK_END);
fsize = ftell(pf);
rewind(pf);
printf("File has %ld bytes!\n", fsize);
}
// write OK response file name
bzero(buffer, sizeof(buffer));
bcopy(filename, buffer, sizeof(buffer));
printf("\n\n\n\n%s\n\n\n\n", buffer);
n = write(newsockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("ERROR writing to socket");
exit(1);
}
close(newsockfd);
close(sockfd);
return 0;
}
Client.cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
if (argc < 3)
{
fprintf(stderr, "usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
// init sockfd
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("sockfd error");
exit(1);
}
// init server
server = gethostbyname(argv[1]);
if (server == NULL)
{
fprintf(stderr, "ERROR, no such host\n");
exit(0);
}
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
serv_addr.sin_port = htons(portno);
// connect
if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
perror("ERROR connecting");
exit(1);
}
// recive and set buffer size:
char tempBuff[10];
bzero(tempBuff, 10);
n = read(sockfd, tempBuff, sizeof(tempBuff));
if (n < 0)
{
perror("fail to recive buffer size");
exit(1);
}
char buffer[stol(string(tempBuff))];
printf("Connect succes, Buffer size is %ld Bytes\n", sizeof(buffer));
// input file:
printf("Input file name to download: ");
string filename;
cin >> filename;
// Send filename
bzero(buffer, sizeof(buffer));
bcopy(filename.c_str(), buffer, filename.length());
n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
{
perror("ERROR writing to socket");
}
// read file name response
bzero(buffer, sizeof(buffer));
n = read(sockfd, buffer, sizeof(buffer));
if (n < 0)
{
perror("ERROR reading from socket");
}
printf("\n\n\n\n%s, %ld\n\n\n\n", buffer, strlen(buffer));
// if (strcmp(buffer, filename.c_str()) == 0)
// {
// printf("OK!\n");
// }
// else
// {
// perror("Wrong filename");
// printf("server msg: %s\n", buffer);
// exit(1);
// }
close(sockfd);
return 0;
}
RUN CODE WITH FOLLOWING COMMAND:
Client: ./client [server ip] [port]
Server: ./server [port]
My result:
Update 1: problem disappear when i remove these line:
// write buff size
int buffsize;
printf("Input recive buffsize in Byte: ");
scanf("%d", &buffsize);
if (buffsize <= 0)
{
perror("Buffer size must be > 0");
exit(1);
}
at server.cpp
and these line:
// recive and set buffer size:
bzero(tempBuff, sizeof(tempBuff));
n = read(sockfd, tempBuff, sizeof(tempBuff));
if (n < 0)
{
perror("fail to recive buffer size");
exit(1);
}
// char buffer[stol(string(tempBuff))];
at client.cpp
I solved it. this problem occur due to tempBuff is too small. it's just 10 bytes. Using bigger tempBuff will solve the problem.
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...
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.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I have seen that some of the c++ header file in windows has alternative in linux. Here I have created socket program and one more string processing program in linux-c++.
Is it possible to modify such that same code works in both windows as well in linux?
code 1:
#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 <sstream.h>
#include <pthread.h>
#include <iostream>
#include <sstream>
#include <cstdio>
#include <vector>
#include <map>
#include "dictionary_exclude.h"
#pragma GCC diagnostic ignored "-Wwrite-strings"
void *SocketHandler(void *);
int main(int argv, char **argc)
{
int host_port = 1103;
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 to manage requests from multiple clients
pthread_detach(thread_id);
} else {
fprintf(stderr, "Error accepting %dn", errno);
}
}
FINISH:
;
}
void *SocketHandler(void *lp)
{
int ar[10];
int result=0;
int *csock = (int *) lp;
char buf[20];
int k;
const unsigned int MAX_BUF_LENGTH = 4096;
std::vector<char> buffer(MAX_BUF_LENGTH);
std::string input;
int bytesReceived = 0;
//char buffer[1024];
int buffer_len = 1024;
int bytecount;
int i = 0;
std::string current;
std::vector<std::string> sentences;
if ((bytecount = recv(*csock, (char*) input.c_str(), input.length(), 0)) == -1) {
fprintf(stderr, "Error receiving data %d \n", errno);
goto FINISH;
}
do {
bytesReceived = recv(*csock, buffer.data(), buffer.size(), 0);
// append string from buffer.
if ( bytesReceived == -1 )
{
fprintf(stderr, "Error receiving data %d \n", errno);
goto FINISH;
}
else
input.append( buffer.cbegin(), buffer.cend() );
} while ( bytesReceived == MAX_BUF_LENGTH );
while(i < input.length())
{
current += input[i];
if(input[i] == '"')
{
int j = i + 1;
while( j < input.length() && input[j] != '"')
{
current += input[j];
j ++;
}
current += input[j];
i = j + 1;
}
if(input[i] == '.' || input [i] == '!' || input[i] == '?')
{
sentences.push_back(current);
current = "";
}
i ++;
}
for(i =0; i<sentences.size(); i++)
{
std::cout << i << " -> " << sentences[i] << std::endl;
}
if ((bytecount = send(*csock, (char *)ar, i *sizeof(int), 0)) == -1) { // Here we cant send lenth-1. It consider exact
fprintf(stderr, "Error sending data %d\n", errno);
goto FINISH;
}
FINISH:
free(csock);
return 0;
}
code 2:
#include<stdio.h>
#include<string.h>
#include "client.h"
int main(int argc, char *argv[] )
{
const char *buffer;
const char *ch;
std::string input = argv[1];
int ar[2];
printf("Client : \n");
if ( argc != 2 ) /* argc should be 2 for correct execution */
{
printf( "\n%s filename\n", argv[0] );
}
else
{
ch=client(input);
ar[0]=((int*)ch)[0];
ar[1]=((int*)ch)[1];
}
printf("\n #ar[0]=%d;ar[1]=%d# \n",ar[0],ar[1]);
return ar[1];
}
header file
#include <iostream>
#ifndef client_h__
#define client_h__
extern char *client(std::string string_input);
#endif
Sockets and threads do not have a standard API used by both Windows and Linux. Although they are somewhat similar, you will have to modify your code in order to get it to work for windows.
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.