I am just wondering why this crashes when a client connects?? Its supposed to be a simple TCP server that when the client connects and sends a string, the server responds with the number of A's in the string. The server crashes as soon as the client types a letter in.
#include<io.h>
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
int main(int argc , char *argv[])
{
WSADATA wsa;
SOCKET s , new_socket, master;
struct sockaddr_in server , address;
int c, valread;
char *message = "Welcome to Marshall's TCP Server!!";
int MAXRECV = 1024;
char *buffer;
char AmmtA = 'a';
char AmmtB = 'A';
int count = 0, x;
fd_set readfds;
buffer = (char*) malloc((MAXRECV + 1) * sizeof(char));
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 9000 );
//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
//Listen to incoming connections
listen(s , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while( (new_socket = accept(s , (struct sockaddr *)&address, &c)) != INVALID_SOCKET )
{
puts("Connection accepted");
send(new_socket , message , strlen(message) , 0);
valread = recv( new_socket , buffer, MAXRECV, 0);
if( valread == SOCKET_ERROR)
{
int error_code = WSAGetLastError();
if(error_code == WSAECONNRESET)
{
//Somebody disconnected , get his details and print
printf("Host disconnected unexpectedly , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
//Close the socket and mark as 0 in list for reuse
closesocket( s );
}
else
{
printf("recv failed with error code : %d" , error_code);
}
}
if ( valread == 0)
{
//Somebody disconnected , get his details and print
printf("Host disconnected , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
//Close the socket and mark as 0 in list for reuse
closesocket( s );
}
else
{
for (x = 0; buffer[x] != '\0'; x++) {
if (buffer[x] == AmmtA || buffer[x] == AmmtB)
count++;
}
char feedback[150];
sprintf(feedback, "There is %d A's in your string", count);
feedback[MAXRECV] = '\0';
printf("%s:%d - %s \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port), buffer);
send( s , feedback , MAXRECV , 0 );
}
free(buffer);
}
if (new_socket == INVALID_SOCKET)
{
printf("accept failed with error code : %d" , WSAGetLastError());
return 1;
}
closesocket(s);
WSACleanup();
return 0;
}
10057 - WSAENOTCONN - Socket is not connected.
The send call is correct and it uses new_socket. But the recv call uses socket/sd "s". The recv call should also use new_socket.
The error 10057 is returned because s is only bound to the local end point and not connected with the remote end whereas the new socket returned by the accept connected to the remote end.
for (x = 0; buffer[x] != '\0'; x++) {
if (buffer[x] == AmmtA || buffer[x] == AmmtB)
count++;
}
Why are you comparing buffer[x] to 0. There's no special reason any particular entry in the buffer should be zero, and this can easily read off the end of the buffer. Perhaps you think buffer contains a string. But it doesn't. It contains whatever you read from the socket, and it has no special format or terminator.
Fortunately, you do know the number of bytes you read. You stored that in valread, so you want:
for (x = 0; x < valread; x++) {
Related
I need to create a simple modbus application that will transfer data in bool type. I created client and server codes for this.
Client side:
int Client(bool message[8])
{
struct sockaddr_in si_other;
int s, slen=sizeof(si_other);
bool buf[BUFLEN];
WSADATA wsa;
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
exit(EXIT_FAILURE);
return 1;
}
if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
{
exit(EXIT_FAILURE);
return 2;
}
memset((bool *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
si_other.sin_addr.S_un.S_addr = inet_addr(SERVER);
if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen) == SOCKET_ERROR)
{
exit(EXIT_FAILURE);
return 3;
}
// closesocket(s);
// WSACleanup();
return 0;
}
Server side:
int main()
{
SOCKET s;
struct sockaddr_in server, si_other;
int slen , recv_len;
bool buf[BUFLEN];
WSADATA wsa;
slen = sizeof(si_other) ;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
if((s = socket(AF_INET , SOCK_DGRAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( PORT );
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
while(1)
{
printf("Waiting for data...\n");
fflush(stdout);
memset(buf,'0', BUFLEN);
if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
for (int i=0; i<=7; i++) {
printf("%d", buf[i]);
}
printf("Data: %d\n" , buf);
printf("%s-%s-%s\n",buf[0],buf[1],buf[2]); //When I run this code, it works just like the code with 'for' and gives an error.
if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == SOCKET_ERROR)
{
printf("sendto() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
}
closesocket(s);
WSACleanup();
return 0;
}
When I run the application, the data transfer is not correct. For example, when I send data as '101010', it transmits '100000'; If send data as '110101', it transmits '110000' or if send it as '011111', it transmits '000000'. In other words, in order to read a data with a value of '1' correctly, all the values before that data must be '1'.
When I remove the 'for' part in the code and try to read the whole buf directly ( printf("Data: %d\n" , buf) ) , it reads '6421972' data. Even if I change the data, this number does not change. What can I do to overcome this problem?
In your client, strlen(message) will count chars until the first '0'encoutered. So your sent bool array never will be of length 8.
Your client must then take the buffer length too in parameter to fix this.
If your buffer is a true C array (not an allocated pointer) then sizeof statement can give the length. But if you use a malloc'd pointer for buf, sizeof statement will always return 8, never less, never more (in 64 bit systems), that is the size of a pointer only.
In short, always keep a length integer alongside with a buffer.
I have created simple TCP server using winsock2.h library. It translates english words into lithuanian for clients. I recieve query from client like this:
int MAXRECV = 100;
char *buffer;
buffer = (char*) malloc((MAXRECV + 1) * sizeof(char));
valread = recv(new_socket, buffer, MAXRECV, 0);
buffer[valread] = '\0';
After that, I want to open a dictionary and find that word translation in a file. Here is a function call and function itself.
char *lithuanianWord;
lithuanianWord = (char*) malloc((MAXWORDSIZE + 1) * sizeof(char));
if (findTranslation(buffer, &lithuanianWord)) {
send(new_socket, lithuanianWord, strlen(lithuanianWord), 0);
} else {
lithuanianWord = "Translation not found";
send(new_socket, lithuanianWord, strlen(lithuanianWord), 0);
}
int findTranslation (char* word, char** lithuanianWord) {
FILE *fp;
int translationFound = 0;
const char englishWord[50];
char buffer[255];
fp = fopen("*\\dictionary.txt","r");
while((fgets(buffer,255,fp)) != NULL) {
sscanf(buffer,"%s%s", englishWord, lithuanianWord);
if(strcmp(englishWord, word)==0 ) {
translationFound = 1;
break;
}
}
fclose(fp);
return translationFound;
}
Code compiles and runs perfectly. The problem is that txt file does not open and answer is always "Translation not found". This function works fine when stand alone. Path is full and the same, I just shortened it.
Error I get: No such file or directory. Both client and server are runing on the same hardware.
Update: full server code.
#include<io.h>
#include<stdio.h>
#include<winsock2.h>
#include<string.h>
int findTranslation (char* word, char** translation);
int main(int argc , char *argv[])
{
WSADATA wsa;
SOCKET master , new_socket, client_socket[30], s;
struct sockaddr_in server , address;
int max_clients = 30, activity, addrlen, i, valread;
char *lithuanianWord;
int MAXWORDSIZE = 100;
lithuanianWord = (char*) malloc((MAXWORDSIZE + 1) * sizeof(char));
//size of our receive buffer, this is string length.
int MAXRECV = 100;
//set of socket descriptors
fd_set readfds;
//1 extra for null character, string termination
char *buffer, *message;
buffer = (char*) malloc((MAXRECV + 1) * sizeof(char));
for(i = 0 ; i < 30;i++)
{
client_socket[i] = 0;
}
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//Create a socket
if((master = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
//Bind
if( bind(master ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
}
puts("Bind done");
listen(master , 3);
puts("Waiting for incoming connections...");
addrlen = sizeof(struct sockaddr_in);
for(;;)
{
//clear the socket fd set
FD_ZERO(&readfds);
//add master socket to fd set
FD_SET(master, &readfds);
//add child sockets to fd set
for ( i = 0 ; i < max_clients ; i++)
{
s = client_socket[i];
if(s > 0)
{
FD_SET( s , &readfds);
}
}
//wait for an activity on any of the sockets, timeout is NULL , so wait indefinitely
activity = select( 0 , &readfds , NULL , NULL , NULL);
if ( activity == SOCKET_ERROR )
{
printf("select call failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
//If something happened on the master socket , then its an incoming connection
if (FD_ISSET(master , &readfds))
{
if ((new_socket = accept(master , (struct sockaddr *)&address, (int *)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
//inform user of socket number - used in send and receive commands
printf("New connection , socket fd is %d , ip is : %s , port : %d \n" , new_socket , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
//add new socket to array of sockets
for (i = 0; i < max_clients; i++)
{
if (client_socket[i] == 0)
{
client_socket[i] = new_socket;
printf("Adding to list of sockets at index %d \n" , i);
break;
}
}
valread = recv(new_socket, buffer, MAXRECV, 0);
buffer[valread] = '\0';
printf("%s:%d - %s \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port), buffer);
int i = findTranslation(buffer, &lithuanianWord);
if (i == 1) {
send(new_socket, lithuanianWord, strlen(lithuanianWord), 0);
} else {
lithuanianWord = "Vertimas nerastas";
send(new_socket, lithuanianWord, strlen(lithuanianWord), 0);
}
}
//else its some IO operation on some other socket
for (i = 0; i < max_clients; i++)
{
s = client_socket[i];
//if client present in read sockets
if (FD_ISSET( s , &readfds))
{
//get details of the client
getpeername(s , (struct sockaddr*)&address , (int*)&addrlen);
//Check if it was for closing , and also read the incoming message
//recv does not place a null terminator at the end of the string (whilst printf %s assumes there is one).
valread = recv( s , buffer, MAXRECV, 0);
buffer[valread] = '\0';
if( valread == SOCKET_ERROR)
{
int error_code = WSAGetLastError();
if(error_code == WSAECONNRESET)
{
//Somebody disconnected , get his details and print
printf("Host disconnected unexpectedly , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
//Close the socket and mark as 0 in list for reuse
closesocket( s );
client_socket[i] = 0;
}
else
{
printf("recv failed with error code : %d" , error_code);
}
}
if ( valread == 0)
{
//Somebody disconnected , get his details and print
printf("Host disconnected , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
//Close the socket and mark as 0 in list for reuse
closesocket( s );
client_socket[i] = 0;
}
//Echo back the message that came in
else
{
i = findTranslation(buffer, &lithuanianWord);
if (i == 1) {
send(s, lithuanianWord, strlen(lithuanianWord), 0);
} else {
lithuanianWord = "Vertimas nerastas";
send(s, lithuanianWord, strlen(lithuanianWord), 0);
}
}
}
}
}
closesocket(s);
WSACleanup();
return 0;
}
int findTranslation (char* word, char** lithuanianWord) {
FILE *fp;
int translationFound = 0;
const char englishWord[50];
char buffer[255];
fp = fopen("C:\\Users\\Martynas\\Documents\\Programų_sistemos\\IV semestras\\Tinklai\\async\\dictionary.txt","r");
if (fp == NULL) {
perror("Error");
}
while((fgets(buffer,255,fp)) != NULL) {
sscanf(buffer,"%s%s", englishWord, lithuanianWord);
if(strcmp(englishWord, word)==0 ) {
translationFound = 1;
break;
}
}
fclose(fp);
return translationFound;
}
I am currently working on a Proxy that should get the browser's request, forward it to the server and then return the server's reply so that the requested page can download.The proxy should support both HTTP 1.0 and 1.1.
I have to write this program in C, with socket programming, but I am new in both (I have only ever programmed in Ada). So I tried to write something, but as soon as I run my program and try to connect, I get a "Segmentation fault" error and I don't know what it could mean. I've read that it was about pointers/strings and memory, but I don't know why I'm getting these errors.
here is my code:
#include<stdio.h>
#include<string.h> //strlen
#include<stdlib.h> //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h> //write
#include<netdb.h> //hostent
int main(int argc , char *argv[])
{
int socket_desc , new_socket ;
struct sockaddr_in server , client;
char message_from_browser[2000];
int len;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("bind failed");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
int c;
c = sizeof(struct sockaddr_in);
while( (new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
puts("Connection accepted");
if (new_socket<0)
{
perror("accept failed");
return 1;
}
close(socket_desc); // don't need this anymore
puts("okay dude??");
if (recv(new_socket, message_from_browser, 2000, 0)<=0)
{
puts("error: connection");
}
puts(message_from_browser);
puts ("Request Received!");
puts("okay huhhh??");
// oKAY i receive the request! Now extract the hostname from the request!
char my_hostname[256];
int j=0;
puts("we created j so");
// doesn't workkkkk: Segmentation error
while (j < strcspn(strstr(message_from_browser, "www."), "/"))
{
my_hostname[j] = strstr(message_from_browser, "www.")[j];
j++;
puts(j);
}
puts("hostname found! It is: \r");
puts(my_hostname);
char *hostname = my_hostname;
char ip[100];
struct hostent *he;
struct in_addr **addr_list;
int i;
if ( (he = gethostbyname( hostname ) ) == NULL)
{
//gethostbyname failed
herror("gethostbyname");
return 1;
}
//Cast the h_addr_list to in_addr , since h_addr_list also has the ip address in long format only
addr_list = (struct in_addr **) he->h_addr_list;
for(i = 0; addr_list[i] != NULL; i++)
{
//Return the first one;
strcpy(ip , inet_ntoa(*addr_list[i]) );
}
printf("we now have the ip we want to connect to and it is: %s \n", ip);
// CLIENT SIDE
struct sockaddr_in actual_server;
char server_reply[2000];
int socket_client;
socket_client = socket(AF_INET , SOCK_STREAM , 0);
if (socket_client <0 )
{
puts("error: couldn't create socket");
}
// remove the "http" from the message of the browser
/*char message_from_browser_edited[2000];
char token_1[1993];
char token_2[4];
int k=0;
int l=0;
int m=0;
while (k < strcspn(message_from_browser, "http"))
{
token_1[k] = message_from_browser[k];
k++;
}
while (l < 1992)
{
my_hostname[l] = strstr(message_from_browser, "http")[l];
l++;
}
for (m=0; m<=1992; m++)
{
if (m<=3)
message_from_browser_edited[m] = token_1[m] ;
else
message_from_browser_edited[m] = token_2[m-4];
}
puts("We edited the browser's message");
puts(message_from_browser_edited);*/
// now we have the true message from the browser
if (write(socket_client, message_from_browser, 2000 )<0)
{
puts("error: wouldn't write :(");
}
puts("written!");
// client reaching actual server
actual_server.sin_addr.s_addr = inet_addr(ip); // ip is the result of gethostbyname
actual_server.sin_family = AF_INET;
actual_server.sin_port = htons( 80 ); // it's 80 bc the client side of the proxy is now trying to access the actual internet
if (connect(socket_client , (struct sockaddr *)&actual_server , sizeof(actual_server)) < 0)
{
puts("connect error");
return 1;
}
puts("Connected!!!");
if( send(socket_client , message_from_browser, 2000 , 0) < 0)
{
puts("Send failed :( ");
return 1;
}
puts("Data Send!!!!");
//Receive a reply from the server
if( recv(socket_client, server_reply , 2000 , 0) < 0)
{
puts("recv failed");
}
puts("Reply received\n");
puts(server_reply);
puts(" ");
// BACK TO THE SERVER SIDE that will send the message back to the browser.
if (send(new_socket, server_reply, 2000, 0) == -1)
{
perror("send");
close(new_socket);
exit(0);
}
close(new_socket); // parent doesn't need this
} // this is for the while
return 0;
} // this is the main
I've scattered a few messages here and there to pinpoint where exactly the problem is and I found out that it's where I try to extract the host name from the browser's request (I put a comment here that says I got a Segmentation Error). This is weird because it used to work before I made other changes, so I put the changes in comments in hope that it would work again but it doesn't... So I really don't understand what could be wrong. I know that the error is in the while loop's statements but I don't know what's wrong with what I wrote ((j < strcspn(strstr(message_from_browser, "www."), "/"))). Is there any way to fix that issue? And am I even doing the right thing for the proxy to work?
Thank you!
I have updated my code to this based on research:
while (number_of_connections--) {
client_sock = socket(AF_INET , SOCK_STREAM , 0);
if (connect(client_sock , (struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("connect failed. Error");
}
printf("socket %d created\n", client_sock);
pthread_t sniffer_thread;
new_sock = malloc(1);
*new_sock = client_sock;
if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0)
{
perror("could not create thread");
return 1;
}
}
Then I'm handling it with this function:
void *connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = *(int*)socket_desc;
int read_size, cursor;
char *message , client_message[2000];
//Send some messages to the client
char handshakeBuf[sizeof(handshake)];
memcpy(handshakeBuf, &handshake, sizeof(handshake));
handshake.a++;
handshake.c = 0xac;
handshake.d = 0x0d;
//Send some data
if( send(sock , handshakeBuf , sizeof(handshakeBuf) , 0) < 0)
{
puts("Send failed");
}
//keep communicating with server
while(1)
{
//Receive a reply from the server
if( recv(sock , client_message , 2000 , 0) < 0)
{
puts("recv failed");
break;
}
puts(client_message);
}
close(sock);
return 0;
}
Now my problem is why does it suddenly stop when it reaches the 4th connection?
Original Question
I am trying to write my first C client. I needed to create 4 connections to the server from one client to simulate 4 clients connected where each connection of course has its own handler.
Here is what I have so far:
void connect_to_server(struct sockaddr_in server);
int main(int argc , char *argv[])
{
int number_of_connections, x;
struct sockaddr_in server;
server.sin_addr.s_addr = inet_addr("ipaddress");
server.sin_family = AF_INET;
server.sin_port = htons( port );
number_of_connections = 4;
for ( x = 0; x < number_of_connections; x++ ) {
connect_to_server(server);
}
return 0;
}
void connect_to_server(struct sockaddr_in server) {
int sock;
char message[1000] , server_reply[2000];
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
printf("Could not create socket");
}
puts("Socket created");
if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("connect failed. Error");
}
while(1)
{
scanf("%s" , message);
if( send(sock , message , strlen(message) , 0) < 0)
{
puts("Send failed");
}
if( recv(sock , server_reply , 2000 , 0) < 0)
{
puts("recv failed");
break;
}
puts(server_reply);
}
close(sock);
}
Well I'm obviously also new to C. So what is wrong? Should I declare more sockets like: int sockA, sockB, sockC, sockD or I guess its the while loop inside the connect_to_server?
It seems the new version of the implementation uses multithreading: pthread_create(...) function call. But is there an implementation of waiting after the threads are created?
For example, the waiting can be implemented:
by using pthread_join(...) function call;
by waiting for specific key press event using getchar() function call.
Notes
Please be careful with these statements:
if (send(sock, handshakeBuf, sizeof(handshakeBuf), 0) < 0)
if (recv(sock, client_message, 2000 , 0) < 0)
The send() and recv() functions do not guarantee that the entire buffer will be sent/received after one function call. The functions return the actual number of sent/received bytes.
Please introduce analysis of the returned value for send() and recv() function calls: continue sending if not all bytes are sent, continue receiving if "not enough" bytes are received. Also, there is an article related to the some basics of the network programming: TCP/IP client-server application: exchange with string messages.
I have two programs for server and client. My server can connect to multiple client. But the problem right now I am facing is that, I want to display some message from the server side to client side but I am unable to do that. Both the server and client program are provided below. I think the syntax that is preventing me to print the message on the client side is scanfwhich is used the code of client (second line of the while loop). I am not getting any solution for that about how to display the two messages from the server side when the client will get connected.
Problem 1:
Server side messages that I want to display on the client side when client gets connected : (can be found in the new_connection_handler function)
message = "This is connection handler\n";
message = "Type something \n";
Problem 2:
Why I need to use the sleep (2) on the client side? If I do not use the sleep (2), then I cannot receive the data sent by the client on the client side. The data shows when I send something second time from the client side.
Problem 3:
Is it possible to write both the client and server code together and compile and run it using command line arguments?
Server Code:
#include<stdio.h>
#include<string.h> //strlen
#include<stdlib.h> //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h> //write
#include<pthread.h> //for thread
#define MAX_CLIENTS 5
//the thread function
void *new_connection_handler(void *);
int main(int argc , char *argv[])
{
int socket_desc , client_sock , c , *new_sock;
struct sockaddr_in server , client;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
bzero (&server.sin_zero, 8);
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind failed. Error");
return 1;
}
//Listen
listen(socket_desc , MAX_CLIENTS);
//Accept and incoming connection
printf("Waiting for incoming connections\n");
c = sizeof(struct sockaddr_in);
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
printf("Connection accepted");
pthread_t thread_id;
if( pthread_create( &thread_id , NULL , new_connection_handler , (void*) &client_sock) < 0)
{
perror("could not create thread");
return 1;
}
printf("Handler assigned\n");
}
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
return 0;
}
void *new_connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = *(int*)socket_desc;
int read_size;
char *message , client_message[2000];
//Send some messages to the client
message = "This is connection handler\n";
write(sock , message , strlen(message));
message = "Type something \n";
write(sock , message , strlen(message));
//Receive a message from client
while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
{
//Send the message back to client
write(sock , client_message , strlen(client_message));
}
if(read_size == 0)
{
printf("Client disconnected\n");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
//Free the socket pointer
free(socket_desc);
return 0;
}
Client Code:
#include<stdio.h> //printf
#include<string.h> //strlen
#include<sys/socket.h> //socket
#include<arpa/inet.h> //inet_addr
int main(int argc , char *argv[])
{
int sock;
struct sockaddr_in server;
char message[1000] , server_reply[2000];
int len;
//Create socket
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
printf("Could not create socket");
}
puts("Socket created");
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons( 8888 );
//Connect to remote server
if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("connect failed. Error");
return 1;
}
puts("Connected\n");
//keep communicating with server
while(1)
{
printf("Enter message : ");
scanf("%s" , message);
//Send some data
if( send(sock , message , strlen(message) , 0) < 0)
{
puts("Send failed");
return 1;
}
sleep (2);
//Receive a reply from the server
if((len = recv(sock , server_reply , 2000 , 0)) < 0)
{
puts("recv failed");
break;
}
puts("Server reply :");
server_reply [len]='\0';
printf("%s\n", server_reply);
}
close(sock);
return 0;
}
Your frames are out of sync You open your client handling thread with two sends from the server. Without your "sleep", you pick up one, but not the other. your buffer sizes are also not being used correctly, as they're inconsistently being treated as terminated strings when in fact their send length is based on strlen (which is ok, so long as it is consistent).
I think this is what you're trying to do, with a few modifications:
Client Code
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdint.h>
int main(int argc , char *argv[])
{
int sock;
struct sockaddr_in server;
char message[1000] , server_reply[2000];
int len;
//Create socket
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
printf("Could not create socket");
}
puts("Socket created");
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons( 8888 );
//Connect to remote server
if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("connect failed. Error");
return 1;
}
puts("Connected\n");
//keep communicating with server
while((len = recv(sock, server_reply, sizeof(server_reply), 0)) > 0)
{
printf("Server reply: %.*s", len, server_reply);
printf("Enter message : ");
if (fgets(message, sizeof(message), stdin) == NULL)
break;
//Send some data
if( send(sock , message , strlen(message) , 0) < 0)
{
puts("Send failed");
return 1;
}
}
close(sock);
return 0;
}
Server Code
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<pthread.h>
#include<stdint.h>
#define MAX_CLIENTS 5
//the thread function
void *new_connection_handler(void *);
int main(int argc , char *argv[])
{
int socket_desc , client_sock;
struct sockaddr_in server , client;
socklen_t c = sizeof(client);
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
bzero (&server.sin_zero, 8);
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind failed. Error");
return 1;
}
//Listen
listen(socket_desc , MAX_CLIENTS);
//Accept and incoming connection
printf("Waiting for incoming connections\n");
c = sizeof(client);
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, &c)) )
{
printf("Connection accepted");
pthread_t thread_id;
if( pthread_create( &thread_id , NULL , new_connection_handler , (void*) (intptr_t)client_sock) < 0)
{
perror("could not create thread");
return 1;
}
printf("Handler assigned\n");
}
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
return 0;
}
void *new_connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = (intptr_t)socket_desc;
int read_size = 0;
char client_message[2000];
static const char rdy[] = "READY\n";
write(sock, rdy, sizeof(rdy)-1);
//Receive a message from client
while( (read_size = recv(sock , client_message , sizeof(client_message) , 0)) > 0 )
write(sock , client_message , read_size);
if(read_size == 0)
{
printf("Client disconnected\n");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
return 0;
}
This still needs better join-logic on the client threads, but if you paste and compile each with appropriate flags I think it does what you're trying to achieve.
Best of luck.