Sending/receiving strings with sockets - c

Here's a simple code tcp client/server where the server sends "Hello from Server" after connection established. My problems are:
1) client writes the string after i close the server.exe window and don't know why;
2) client prints strange characters and not "Hello from server". I miss something in the output format.
SERVER
#if defined WIN32
#include <winsock2.h>
#else
#define closesocket close
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#define PROTOPORT 5193 //default protocol port number
#define QLEN 6 // size of request queue
#define BUFFERSIZE 10
void ErrorHandler (char *errorMessage) {
printf (errorMessage);
}
void ClearWinSock() {
#if defined WIN32
WSACleanup ();
#endif
}
int main(void) {
#if defined WIN32
WSADATA wsaData;
int iResult = WSAStartup (MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
ErrorHandler ("Error at WSAStartup()\n");
return 0;
}
#endif
// CREAZIONE DELLA SOCKET
int MySocket;
MySocket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (MySocket < 0) {
ErrorHandler ("socket creation failed.\n");
ClearWinSock();
return 0;
}
// ASSEGNAZIONE DI UN INDIRIZZO ALLA SOCKET
struct sockaddr_in sad;
memset (&sad, 0, sizeof (sad)); //ensures that extra bytes contain 0
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = inet_addr ("127.0.0.1"); //ip del server con conversione
//da notazione dotted-decimal in un numero a 32 bit
//espresso nella rappresentazione della rete
sad.sin_port = htons (5193); //host to network short
//Assegnazione porta e ip alla socket e verifica presenza di eventuali errori
if (bind (MySocket, (struct sockaddr*) & sad, sizeof (sad)) < 0) {
ErrorHandler ("bind() failed.\n");
closesocket (MySocket);
ClearWinSock ();
return 0;
}
// SETTAGGIO DELLA SOCKET ALL'ASCOLTO
if (listen (MySocket, QLEN) < 0) {
ErrorHandler ("listen() failed.\n");
closesocket (MySocket);
ClearWinSock ();
return 0;
}
// ACCETTARE UNA NUOVA CONNESSIONE - e creazione di una nuova socket per comunicare con il client
struct sockaddr_in cad; //structure for the client address
int clientSocket; // socket descriptor for the client
int clientLen; //the size of the client address
printf ("Waiting for a client to connect...");
while (1) {
clientLen = sizeof (cad); //set the size of the client address
if ((clientSocket = accept (MySocket, (struct sockaddr*) &cad, &clientLen)) < 0) {
ErrorHandler ("accept() failed.\n");
// CHIUSURA DELLA CONNESSIONE
closesocket (MySocket);
ClearWinSock ();
return 0;
}
printf ("Handling client %s\n", inet_ntoa (cad.sin_addr));
}
char* inputString = "Hello from server"; // Stringa da inviare
int stringLen = strlen (inputString); // Determina la lunghezza
// INVIARE DATI AL CLIENT
if (send (clientSocket, inputString, stringLen, 0) != stringLen) {
ErrorHandler ("send () sent a different number of bytes than expected");
closesocket (clientSocket);
ClearWinSock();
system("pause");
return 0;
}
closesocket(MySocket);
ClearWinSock ();
return 0;
}
CLIENT
#if defined WIN32
#include <winsock2.h>
#else
#define closesocket close
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#define BUFFERSIZE 20 // Dimensione buffer che riceve dati dal server
#define PROTOPORT 5193 // Numero di porta di default
void ErrorHandler (char *errorMessage) {
printf (errorMessage);
}
void ClearWinSock () {
#if defined WIN32
WSACleanup();
#endif
}
int main (void) {
#if defined WIN32
WSADATA wsaData;
int iResult = WSAStartup (MAKEWORD (2,2), &wsaData);
if (iResult !=0) {
printf ("error at WSASturtup\n");
return 0;
}
#endif
// CREAZIONE DELLA SOCKET
int Csocket;
Csocket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (Csocket < 0) {
ErrorHandler ("socket creation failed.\n");
closesocket (Csocket);
ClearWinSock ();
return 0;
}
// COSTRUZIONE DELL'INDIRIZZO DEL SERVER
struct sockaddr_in sad;
memset (&sad, 0, sizeof (sad));
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = inet_addr ("127.0.0.1"); //ip del server con conversione
//da notazione dotted-decimal in un numero a 32 bit
//espresso nella rappresentazione della rete
sad.sin_port = htons (5193); // Server port
//CONNESSIONE AL SERVER
if (connect (Csocket, (struct sockaddr*) &sad, sizeof (sad)) < 0) {
ErrorHandler ("Failed to connect.\n");
closesocket (Csocket);
ClearWinSock();
return 0;
}
char buf[BUFFERSIZE];
recv (Csocket, buf, BUFFERSIZE - 1, 0);
printf("Server scrive: %s\n",buf);
// CHIUSURA DELLA CONNESSIONE
closesocket (Csocket);
ClearWinSock();
printf ("\n");
system ("pause");
return 0;
}
In the end: If I would to send more strings, have I to use one send() and one recv() for each of them?

The biggest issue is that you do not break out of the server loop. This is why you don't see anything on the client until you quit the server. The socket gets closed when the program terminates, so the recv call in client no longer blocks. Also, in client you don't check return val from recv and print junk.
Server fix:
while (1) {
clientLen = sizeof (cad); //set the size of the client address
if ((clientSocket = accept (MySocket, (struct sockaddr*) &cad, &clientLen)) < 0) {
....
}
printf ("Handling client %s\n", inet_ntoa (cad.sin_addr));
break; // <- terminate loop,
// or just get rid of the loop altogether as there
// is no real need for it I can see
}
Client fix:
int read = recv (Csocket, buf, BUFFERSIZE - 1, 0);
if (read <= 0) {
// Not successful
}
else {
buf[read] = 0; // Add eos
printf("%s", buf);
}

Related

Sending and receiving a struct over TCP

I have to type two strings in a client and send them with a struct to server. Then the server does c = a + b and sends a news struct with { a, b, c } to client. If a or b received is quit, server sends to client bye.
Client receives the struct and prints c. If it is bye it closes connection, else it returns to asking the input of a and b and the cycle begins again.
Client:
#if defined WIN32
#include <Winsock2.h>
#else
#define closesocket close
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 30
void ClearWinSock() {
#if defined WIN32
WSACleanup();
#endif
}
//-----------------------------INIZIALIZZAZIONE WSADATA
int main (void) {
#if defined WIN32
WSADATA wsaData;
int iResult = WSAStartup (MAKEWORD (2,2), &wsaData);
if (iResult !=0) {
printf ("error at WSASturtup\n");
return 0;
}
#endif
//--------------------------------CREAZIONE SOCKET
int Csocket;
Csocket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (Csocket < 0) {
printf ("socket creation failed");
closesocket (Csocket);
ClearWinSock();
return 0;
}
char s_address[BUFSIZE];
printf ("Inserisci l'indirizzo dell'host a cui connetterti\n");
scanf ("%s", s_address);
int port;
printf ("Inserisci la porta a cui connetterti\n");
scanf("%d", &port);
struct sockaddr_in sad;
memset (&sad, 0, sizeof(sad));
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = inet_addr(s_address);
sad.sin_port = htons (port);
//------------------------------CONNESSIONE AL SERVER
if (connect(Csocket, (struct sockaddr*) &sad, sizeof(sad)) < 0) {
printf ("failed to connect\n");
closesocket (Csocket);
ClearWinSock();
return 0;
}
//-----------------------------RICEZIONE STRINGA DAL SERVER
char buf[BUFSIZE];
int read = recv (Csocket, buf, BUFSIZE - 1, 0);
if (read <=0) {
printf ("Qualcosa non và!\n");
}
else {
buf[read] = '\0'; //tappo stringa per sicurezza
printf("Server scrive: %s\n", buf);
}
//------------------------------STRUTTURA DI STRINGHE
struct stringab {
char a[30];
char b[30];
char c[70];
} ab;
void* abptr = &ab;
printf ("Inserisci prima stringa\n");
scanf ("%s", ab.a);
printf ("Inserisci seconda stringa\n");
scanf ("%s", ab.b);
if (send(Csocket, (char*)abptr, sizeof(ab), 0) != sizeof(ab)) {
printf("client-send() sent a different number of bytes than expected");
closesocket(Csocket);
ClearWinSock();
system ("pause");
return 0;
}
printf ("\n");
closesocket (Csocket);
system ("pause");
ClearWinSock();
return 0;
}
Server:
#if defined WIN32
#include <Winsock2.h>
#else
#define closesocket close
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 30
void ClearWinSock() {
#if defined WIN32
WSACleanup();
#endif
}
int main(void) {
//---------------------------INIZIALIZZAZIONE WSADATA
#if defined WIN32
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf ("Error at WSAStartup");
return 0;
}
#endif
//-------------------------------CREAZIONE SOCKET
int Mysocket;
Mysocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
//Valutare la presenza di errori per assicurarsi che la socket sia valida.
if (Mysocket < 0) {
printf("socket creation failed\n");
return 0;
}
//Assegnazione indirizzo alla socket.
struct sockaddr_in sad;
memset(&sad, 0, sizeof(sad));
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = inet_addr ("127.0.0.1");
sad.sin_port = htons (9888);
//------------------------ASSEGNAZIONE PORTA E IP ALLA SOCKET
if (bind(Mysocket, (struct sockaddr*) &sad, sizeof(sad)) < 0) {
printf ("bind() failed\n");
closesocket(Mysocket);
return 0;
}
//---------------------------SETTAGGIO SOCKET ALL'ASCOLTO
int qlen = 10; //numero client che il server può gestire
if (listen (Mysocket, qlen) < 0) {
printf("listen() failed\n");
closesocket(Mysocket);
return 0;
}
struct sockaddr_in cad; // struttura per l'indirizzo del cient
int Csocket; // descrittore socket per il client
int clientlen; // lunghezza indirizzo del client
//------------------------------ACCETTA LA CONNESSIONE
while (1) {
printf("In attesa di un client con cui comunicare...\n");
memset(&cad, 0, sizeof(cad));
clientlen = sizeof(cad); // assegna la dimensione dell'indirizzo del client
if((Csocket = accept(Mysocket, (struct sockaddr*) &cad, &clientlen)) < 0) {
printf ("accept failed\n");
closesocket(Mysocket);
ClearWinSock();
return 0;
}
printf("Connessione stabilita con il client il cui indirizzo e' %s \n\n", inet_ntoa(cad.sin_addr));
//---------------------------------------INVIO STRINGA AL CLIENT
char* inputString = "Connessione avvenuta!";
int stringlen = strlen(inputString);
if (send(Csocket, inputString, stringlen, 0) != stringlen) {
printf("client-send() sent a different number of bytes than expected");
closesocket(Csocket);
ClearWinSock();
system ("pause");
return 0;
}
printf ("\n");
closesocket (Csocket);
system ("pause");
ClearWinSock();
return 0;
}
So, did I send the struct to server in this manner? How the server could recv() this struct and do c = a + b re-building and re-sending the struct?
I solved the problem on send side and receive side like this:
send(Csocket, (char*)abptr, sizeof(ab), 0);
recv (Csocket, (char*)abptr, sizeof(ab), 0);
So I passed the struct with a struct pointer on both side. I think it's a good solution in local hosting, maybe you need a better one for net (security reasons).

Select blocked using socket in c

The code below is a chatroom. First I run the server, and then the clients. The clients reach the server with sockets. Then the server accepts the connection and the client has to enter his nickname.
I use threads because this way, the fgets is not blocking and multiple clients can reach the server even if a client is slow to enter his nickname.
Until here, there is no problem and everything works, even the select.
After this, the client can introduce a message which is send to all the clients (this is the principle of a chat :P). The problem is that from here, the select doesn't react and stay blocked. Maybe it's because of the FD_set or the threads but actually I don't know and that is the problem.
server.c :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <pthread.h>
#define MYPORT 5555
#define PSEUDO_MAX 30
#define MESSAGE_MAX 1000
#define BACKLOG 10
struct User {
char pseudo[PSEUDO_MAX];
int socket;
struct User *next;
};
struct Thread {
struct User* lst;
fd_set* readfds;
int* max;
int socket;
pthread_mutex_t* mutex;
};
void add(struct User** pp, const char *t, const int sock)
{
struct User *p = malloc(sizeof(*p));
strcpy(p->pseudo, t);
p->socket = sock;
p->next = NULL;
while (*pp)
pp = &(*pp)->next;
*pp = p;
}
void print(const struct User* n)
{
for ( ; n; n = n->next ){
printf("LISTE : %s\n", n->pseudo);
printf("LISTE : %d\n", n->socket);
}
printf("\n");
}
void *thread_pseudo(void *arg)
{
struct Thread* ps_thread = (struct Thread*)arg;
int nsock = ps_thread->socket;
struct User* lst = ps_thread->lst;
int* max = ps_thread->max;
pthread_mutex_t* mutex = ps_thread->mutex;
pthread_mutex_lock(mutex);
fd_set* readfds = ps_thread->readfds;
pthread_mutex_unlock(mutex);
char pseudo[PSEUDO_MAX];
if (send(nsock, "Bienvenue sur le chat !\n",24,0)==-1){
perror("Serveur: send");
}
if (recv(nsock, pseudo, PSEUDO_MAX, 0) == -1) {
perror("Serveur: recv 2: ");
}
pthread_mutex_lock(mutex);
FD_SET(nsock, readfds); // Ajout du nouveau socket au select
*max = (nsock < *max ? *max : nsock);
pthread_mutex_unlock(mutex);
add(&lst, pseudo, nsock);
print(lst);
pthread_exit(NULL);
}
int findSender(fd_set* readfds, const struct User* n){
int socket = 0;
for ( ; n; n = n->next ){
if(FD_ISSET(n->socket, readfds)){
socket = n->socket;
}
}
return socket;
}
int main()
{
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int sockfd2, new_fd; // listen on sock_fd, new connection on new_fd
int max;
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
unsigned int sin_size;
int yes=1;
struct User *lst = NULL; // Initialisation de la liste des Users
struct Thread *ps_thread = malloc(sizeof(*ps_thread)); // Initialisation du struct qui contient les paramètres pour le thread
fd_set readfds;
if ((sockfd2 = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
perror("Serveur: socket 2");
return EXIT_FAILURE;
}
if (setsockopt(sockfd2,SOL_SOCKET,SO_REUSEADDR, &yes,sizeof(int)) == -1) {
perror("Serveur: setsockopt 2");
return EXIT_FAILURE;
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(my_addr.sin_zero), '\0', 8);
if (bind(sockfd2, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
perror("Serveur: bind 2");
return EXIT_FAILURE;
}
if (listen(sockfd2, BACKLOG) == -1) {
perror("Serveur: listen 2");
return EXIT_FAILURE;
}
//Initialisation du fd_set et du max
FD_ZERO(&readfds);
FD_SET(sockfd2, &readfds);
max = sockfd2;
while(1){
if (select(max+1, &readfds, NULL, NULL, NULL) < 0){
printf("error select\n");
}
int sock = findSender(&readfds, lst);
if(FD_ISSET(sockfd2, &readfds)){
new_fd = accept(sockfd2, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
perror("Serveur: accept");
}
pthread_t thread;
ps_thread->lst = lst;
ps_thread->readfds = &readfds;
ps_thread->max = &max;
ps_thread->socket = new_fd;
ps_thread->mutex = &mutex;
if (pthread_create(&thread, NULL, thread_pseudo, ps_thread)) {
perror("pthread_create");
return EXIT_FAILURE;
}
}
else if(FD_ISSET(sock, &readfds)) {
char* message;
int sock = findSender(&readfds, lst);
if (recv(sock, message, MESSAGE_MAX, 0) == -1) {
perror("Serveur: recv 2: ");
}
}
else{
printf("ERROR\n");
}
}
return EXIT_SUCCESS;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <pthread.h>
#define PORT 5555
#define PSEUDO_MAX 30
#define MESSAGE_MAX 1000
void getPseudo(char* pseudo) {
size_t ln = -1;
while (ln <= 0 || ln > PSEUDO_MAX-1) {
printf("Entrez votre pseudo : ");
fgets(pseudo, PSEUDO_MAX, stdin);
ln = strlen(pseudo) - 1;
}
if (pseudo[ln] == '\n')
pseudo[ln] = '\0';
}
void getMessage(char* message) {
size_t ln = -1;
while (ln <= 0 || ln > MESSAGE_MAX-1) {
printf(">");
fgets(message, MESSAGE_MAX, stdin);
ln = strlen(message) - 1;
}
if (message[ln] == '\n')
message[ln] = '\0';
}
void *thread_message(void *arg)
{
printf("Bonjour\n");
char* message;
message = malloc (sizeof(char) * MESSAGE_MAX);
int* sockfd = (int*)arg;
printf("%d\n", *sockfd);
while (1) {
getMessage(message);
if (send(*sockfd, message, strlen(message), 0) == -1){
perror("Client: send message");
}
}
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
int sockfd, numbytes;
struct sockaddr_in their_addr;
// connector's address information
struct hostent *he;
char buf[MESSAGE_MAX];
long int term1, term2, res;
int demande_pseudo = 0;
char* pseudo;
pseudo = malloc (sizeof(char) * PSEUDO_MAX);
if (argc != 2) {
fprintf(stderr, "Donner le nom du serveur.");
return EXIT_FAILURE;
}
if ((he=gethostbyname(argv[1])) == NULL) {
perror("Client: gethostbyname");
return EXIT_FAILURE;
}
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
perror("Client: socket");
return EXIT_FAILURE;
}
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(PORT);
their_addr.sin_addr = *((struct in_addr*)he->h_addr);
memset(&(their_addr.sin_zero), '\0', 8);
if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) {
perror("Client: connect");
return EXIT_FAILURE;
}
while (1) {
if ((numbytes=recv(sockfd, buf, MESSAGE_MAX-1, 0)) == -1) {
perror("Client: recv");
return EXIT_FAILURE;
}
if (demande_pseudo == 0) {
buf[numbytes] = '\0';
printf("%s",buf);
getPseudo(pseudo);
printf("Tu as choisi comme pseudo : %s\n", pseudo);
demande_pseudo++;
printf("%d\n", sockfd);
if (send(sockfd, pseudo, strlen(pseudo), 0) == -1){
perror("Client: send pseudo");
return EXIT_FAILURE;
}
pthread_t thread;
if (pthread_create(&thread, NULL, thread_message, &sockfd)) {
perror("pthread_create");
return EXIT_FAILURE;
}
}
else
{
}
}
close(sockfd);
return EXIT_SUCCESS;
}
Thank you so much for your help
First, your question is confusing, try to be more specific giving some examples.
If I understood your question, your problem is that your select is configured to operate on blocking mode.
This is an example on how to set your socket flags to non-blocking mode.
flags = fcntl(sock, F_GETFL, 0);
if(flags < 0)
err(1, "%s: fcntl", __FUNCTION__);
ret = fcntl(sock, F_SETFL, flags | O_NONBLOCK);
if(ret < 0)
err(1, "%s: fcntl:", __FUNCTION__);
Answer Update
Well, one of your problems is that your main function doesn't wait your thread update readfds and max, thus getting blocked on select with the wrong values for those variables. You could solve that by either adding pthread_join(thread, NULL); after you create your thread OR , as I said first, setting your select as non-blocking mode.
With the second method(non-blocking mode) there will be times you
have nothing to process from select so you need to handle this and not crash. I would use that.
Using the first method (pthread_join) you'll not be able to process incoming
requests while waiting for your thread to finish,hence invalidating the whole purpose of having threads: being available to process incoming requests.
Try to develop those ideas and you'll make that code work! (:

C socket programming: recv always fail

i'm trying to understand C socket programming for an university exam.
I made this simple example:
socket_server.c
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#define SA struct sockaddr
#define MAX_MESS_LEN 16
int main(){
struct sockaddr_in my_addr, cl_addr;
int ret, len, sk, cn_sk;
char cl_ip[INET_ADDRSTRLEN + 1], msg[MAX_MESS_LEN + 1];
sk = socket(AF_INET, SOCK_STREAM, 0); //creo socket TCP/IPv4 listener
printf("socket created! :)\n");
memset(&my_addr, 0, sizeof(my_addr)); //azzero struttura my_addr
my_addr.sin_family = AF_INET; //famiglia protocolli IPv4
my_addr.sin_addr.s_addr = htonl(INADDR_ANY); //in ascolto su qualsiasi interfaccia
my_addr.sin_port = htons(1234); //porta del socket
ret = bind(sk, (SA *) &my_addr, sizeof(my_addr)); //lego il socket alla struttura indirizzo
printf("socket binded! :)\n");
ret = listen(sk, 10); //mi pongo in ascolto sul socket con massimo 10 richieste pendenti
printf("socket listening (on any interface with port 1234)! :)\n");
len = sizeof(cl_addr);
printf("socket is going to wait for a request... zzzzZZZ\n");
cn_sk = accept(sk, (SA *) &cl_addr, &len); //creo il socket connected per la richiesta in cima alla lista
printf("socket accepted request! :D\n");
inet_ntop(AF_INET, &cl_addr.sin_addr, cl_ip, INET_ADDRSTRLEN); //converto indirizzo IPv4 cl_addr.sin_addr in stringa (cl_ip)
printf("IP client: %s\n", cl_ip);
ret = recv(sk, (void *) msg, MAX_MESS_LEN, MSG_WAITALL); //attendo la ricezione di tutti i caratteri della stringa inviata sul socket dal client
msg[MAX_MESS_LEN + 1] = '\0';
printf("received data (%d bytes): %s\n", ret, msg);
if(ret == -1 || ret < MAX_MESS_LEN)
printf("recv ERROR! :(\n");
close(sk); //chiudo il server
}
socket_client.c
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#define SA struct sockaddr
#define MSG_LEN 17
int main(){
struct sockaddr_in srv_addr;
int ret, sk;
char msg[MSG_LEN];
sk = socket(AF_INET, SOCK_STREAM, 0);
printf("Socket created! :)\n");
memset(&srv_addr, 0, sizeof(srv_addr));
srv_addr.sin_family = AF_INET;
srv_addr.sin_port = htons(1234);
ret = inet_pton(AF_INET, "192.168.1.132", &srv_addr.sin_addr);
printf("Trying to establish a connection with 192.168.1.132 on port 1234...");
ret = connect(sk, (SA *) &srv_addr, sizeof(srv_addr)); //faccio una richiesta sul socket
if(ret != -1) printf("Connection established! :D\n");
else printf(" connection error :(\n");
strcpy(msg, "something to send"); //scrivo messaggio in una stringa
printf("sending message: %s\n", msg);
ret = send(sk, (void *) msg, strlen(msg), 0); //invio il messaggio sul socket
if(ret == -1 || ret < strlen(msg))
printf("send ERROR! :(\n");
close(sk);
}
And compiled it with:
gcc socket_client.c -o socket_client
gcc socket_server.c -o socket_server
Maybe it's a stupid question but the recv function in server always fail, there is an example output:
Server:
socket created! :)
socket binded! :)
socket listening (on any interface with port 1234)! :)
socket is going to wait for a request... zzzzZZZ
socket accepted request! :D
IP client: 192.168.1.132
received data (-1 bytes): ����
recv ERROR! :(
Client:
Socket created! :)
Trying to establish a connection with 192.168.1.132 on port 1234...Connection established! :D
sending message: something to send
What's the problem? I don't get it! :( I followed step by step, my teacher's guide.
I'm running on arch linux 64 bit ;)
Thank you for response!
cn_sk = accept(sk, (SA *) &cl_addr, &len); //creo il socket connected per la richiesta in cima alla lista
...
ret = recv(sk, (void *) msg, MAX_MESS_LEN, MSG_WAITALL); //at
You don't recv on the connected socket cn_sk to the client, but instead on the listener socket sk. If you would check the errno you would probably see ENOTCONN.

my program does not open a socket

This is the server part of a chat client server program i wrote. I create a pool of thread and the server must associated a a connected client to a thread. The thread function gestisci() receives commands from clients and sends messages from client1 to client2. But, once i run it, there is nothing appearing on the terminal. Can someone help me?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include<sys/wait.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<pthread.h>
#define BACKLOG_SIZE 5
#define SA struct sockaddr
void* gestisci_richiesta(void*dati)
int main(int argc, char* argv[]) {
printf("in main function\n");
struct sockaddr_in srv_addr, cl_addr;
int ret, sock, cn_sk, porta, t;
struct argomenti{
int sock_cl,stato;
struct sockaddr_in cl_addr;
int index;}
struct argomenti mess[BACKLOG_SIZE];
int arg_cont[BACKLOG_SIZE];
socklen_t len;
int t_free[BACKLOG_SIZE];
pthread_t tid[BACKLOG_SIZE];
if (argc < 2)
printf("errore:inserire numero porta\n");
porta = atoi(argv[1]);
printf(" %d\n", porta);
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock == -1) {
printf("server: impossibile creare un nuovo socket.\n");
return 0;
}
memset(&srv_addr, 0, sizeof(srv_addr));
srv_addr.sin_family = AF_INET;
srv_addr.sin_addr.s_addr = htonl(INADDR_ANY );/* il server si mette in ascolto suqualsiasi delle sueinerfacce di rete*/
srv_addr.sin_port = htons(porta);
ret = bind(sock, (SA*) &srv_addr, sizeof(srv_addr));
if (ret == -1) {
printf("server : impossibile eseguire il bind sul socket.\n");
return 0;
}
printf("bind con successo\n");
listen(sock, BACKLOG_SIZE);
for (t = 0; t < BACKLOG_SIZE; t++) {
t_free[t] = 0;
client[t] = 0;
}
t= 0;
while (1) {
while (t_free[t] != 0)
t = (t + 1) % BACKLOG_SIZE;
t_free[t] = 1;
len = (socklen_t) sizeof(mess[t].cl_addr);
cn_sk = accept(sock, (SA*) &mess[t].cl_addr, &len);
mess[t].sock_cl = cn_sk;
mess[t].index = t;
printf("client:%d connesso\n", t);
if (cn_sk == -1) {
printf("SERVER: errore in attesa di connessione\n");
return 0;
}
if (pthread_create(&tid[t], 0, gestisci_richiesta, (void*) &mess[t])) {
printf("server:impossibile avviare un thread dal pool\n");
return 0;
}
}
}
You are missing \n's on several of those printfs, which will cause them to be buffered instead of printing out immediately.
Other problems exist. Your error message where you call socket() is misleading. There has been no attempt yet to use the port specified. That happens at the bind(). There is no reason to assume the number of clients will equal the backlog size. The size of a sockaddr_in is always the same: no need to recalculate it each time.
you should move t = 0; before while(1).

Using select() in client/server acknowledgement in C

I'm developing in C a Unix application consisting of a server that has to communicate simultaneously with at most five clients. Clients send to server a command which can be tuttomaiuscolo (alltoupper in english) or tuttominuscolo (alltolower) and a string to manipulate; the server receives the two strings and remove from the second word all the characters that are not a-z A-Z characters. If a client sends the string FINE (end) the server has to stop and die (whitout leaving zombie processes).
The problem is the connection between the client and the server. To do this I've used the function select in server and in client too, but the problem is that the select placed in the server (that monitors the reading) doesn't see the client request, so it never goes to the accept function, while the client select (that monitors the writing) returns a value that means it is ready for writing.
Now I'll post the code:
server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <signal.h>
#include <wait.h>
#include <ctype.h>
void ripulisci (char* stringa);
void minuscola (char* orig, char* dest);
void maiuscola (char* orig, char* dest);
void handler(int);
int list;
int sock;
int main () {
int status;
//creo un socket da mettere in ascolto
list = socket (AF_INET, SOCK_STREAM, 0);
if (list < 0) {
perror("Error!");
exit(1);
}
//preparo la struct sockaddr_in
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(2770);
//effettuo il bind
status = bind(list, (struct sockaddr*) &address, sizeof(address));
if (status < 0) {
perror("Error!");
close(list);
exit(1);
}
//mi metto in ascolto
listen(list, 1);
printf("Attendo le connessioni...\n");
//preparo le variabili necessarie per gestire i figli
int esci = 1;
pid_t server[5];
char comando[15];
char lettura[512];
char scrittura[512];
struct sockaddr_in client;
int client_size = sizeof(client);
fd_set fd;
FD_ZERO(&fd);
FD_SET(list, &fd);
struct timeval timer;
//genero i quattro figli/server e mi salvo i pid in un array
int index;
for (index=0 ; index<5 ; index++) {
server[index] = fork();
if (server[index] == 0)
break;
}
//verifico quale processo sono
if (index == 5) {
pause(); //aspetto un segnale da uno dei figli
}
//sono un figlio/server
else {
while(esci) {
timer.tv_sec = 1;
timer.tv_usec = 0;
if (select(list+1, &fd, NULL, NULL, &timer) <= 0) {
printf("Nessun client da servire\n");
continue;
}
if (!FD_ISSET(list, &fd))
continue;
printf("C'è un client\n");
sock = accept(list, (struct sockaddr*) &client, (socklen_t*) &client_size);
if (sock < 0)
break;
printf("Connesso con il client\n");
recv(sock, comando, 15, 0);
recv(sock, lettura, 512, 0);
if (comando[0] == 'F' && comando[1] == 'I' && comando[2] == 'N' && comando[3] == 'E' && comando[4] == '\0')
kill(getppid(), SIGALRM); //al termine dell'esecuzione uscirò
ripulisci(lettura);
//il comando è tuttomaiuscole
if (strcmp("tuttomaiuscolo", comando) == 0) {
maiuscola(lettura, scrittura);
send(sock, scrittura, 512, 0);
}
//il comando è tuttominuscole
else if (strcmp("tuttominuscolo", comando) == 0) {
minuscola(lettura, scrittura);
send(sock, scrittura, 512, 0);
}
//c'è stato un errore
else {
printf ("Error! Command not found\n");
strcpy (scrittura, "error");
send (sock, scrittura, 512, 0);
}
printf("Devo terminare!");
close(sock);
exit(0);
}
}
//termino tutto
for(index=0 ; index<5 ; index++) {
waitpid((int)server[index], NULL, 0);
}
exit(0);
}
void handler(int sig) {
signal(sig, SIG_IGN);
printf("Il server sta terminando in seguito ad una richiesta\n");
close (list);
close (sock);
exit(0);
}
void ripulisci (char* stringa) {
int index = 0;
int app;
while (stringa[index] != '\0' && index<=511) {
if (isalpha(stringa[index])!=1) {
app = index;
do {
stringa[app] = stringa[app+1];
app++;
} while (stringa[app] != '\0');
stringa[app] = '\0';
index--;
}
index++;
}
return;
}
void minuscola (char* orig, char* dest) {
int index = 0;
do {
if (orig[index] < 91)
dest[index] = toupper(orig[index]);
else
dest[index] = orig[index];
index++;
} while (orig[index] != '\0');
dest[index] = '\0';
return;
}
void maiuscola (char* orig, char* dest) {
int index = 0;
do {
if (orig[index] > 91)
dest[index] = tolower(orig[index]);
else
dest[index] = orig[index];
index++;
} while (orig[index] != '\0');
dest[index] = '\0';
return;
}
client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <time.h>
int main () {
int descrittoreSocket;
descrittoreSocket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons(2770);
address.sin_addr.s_addr = INADDR_ANY;
printf ("Connessione in corso...\n");
int ris;
ris = connect(descrittoreSocket, (struct sockaddr*) &address, (socklen_t) sizeof(address));
fd_set fd;
FD_ZERO(&fd);
FD_SET(descrittoreSocket, &fd);
struct timeval timer;
timer.tv_sec = 1;
timer.tv_usec = 0;
if ((ris > -1) && select(descrittoreSocket+1, NULL, &fd, NULL, &timer) >= 0 && FD_ISSET(descrittoreSocket, &fd)) {
printf ("Connessione avvenuta...\n");
char buffer_r [512];
char buffer_w [512];
char command [15];
gets(command);
gets(buffer_r);
send(descrittoreSocket, command, 15, 0);
printf("Spedito!");
fflush(stdout);
send(descrittoreSocket, buffer_w, 512, 0);
printf("Spedito!");
fflush(stdout);
recv(descrittoreSocket, buffer_r, 512, 0);
printf("Trasferito!");
fflush(stdout);
if (strcmp("error", buffer_r) == 0)
printf ("ERROR!");
printf ("%s", buffer_r);
fflush(stdout);
} else {
printf ("Impossibile servire il client\n");
}
close (descrittoreSocket);
exit(0);
}
With syntax higligh:
server: http://pastebin.com/5Nd96JxC
client: http://pastebin.com/aSvR6qVM
Please don't hesitate to ask for clarifications if needed.
Your server shouldn't need to use select with only one listening socket ... instead it should listen for a connection on the listening socket for a client, and when there's a connection, accept it, and then read from the socket the command given by the client. If you want to process more than one request from a client at a time, then you can spin off a separate process or thread for each accepted connection. If you want to avoid blocking behavior during the call to accept by the listening socket, then you can always use ioctl with the FIONBIO flag on the listening socket.
On the client side I also don't see a need for select ... again, there is only one socket on the server to talk to. Simply open a connection on the server, which will block until a connection is made, and when that connection is made, you can read and write to the server.

Resources