I have 3 services in C and I want they communicate toghether with a docker compose but I can't.
I tried with a two simples images and they connected but not in a docker compose.
The problem are the function connect(). He return -1 beaucause in the inet_addr(), I want to include the image who the message will be sent.
I use 3 images with gcc for to compile C files.
# FILE : service1.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
//#define PORT_SERV 4443
#define PORT_CLI 4443
time_t t;
static void * client(){
int clientSocket, ret;
struct sockaddr_in serverAddr;
char buffer[256];
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket < 0) {
printf("[Client -] Error in Client Socket \n");
fflush(stdout);
exit(1);
}
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT_CLI);
serverAddr.sin_addr.s_addr = inet_addr("image1");
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
while (ret < 0) {
printf("[Client -] Erreur de connexion. Nouvel essai ! %d\n", ret);
fflush(stdout);
sleep(3);
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
}
printf("[Client +] Connected to Server.\n");
fflush(stdout);
while(1){
time(&t);
strcpy(buffer, "Bonjour depuis le service 1");
sleep(5);
send(clientSocket, buffer, strlen(buffer), 0);
if (strcmp(buffer, ": exit") == 0) {
printf("[Client -] Disconnected from server.\n");
fflush(stdout);
exit(1);
}
if (recv(clientSocket, buffer, 256, 0) < 0) {
printf("[Client -] Error in receiving data. \n");
fflush(stdout);
} else {
printf("%sService 1 : %s \n", ctime(&t), buffer);
fflush(stdout);
}
}
}
int main(void){
//pthread_t s,
pthread_t c;
int ret = 0;
ret = pthread_create(&c, NULL, &client, NULL);
/*ret = pthread_create(&s, NULL, &server, NULL);
if (! ret) {
ret = pthread_create(&c, NULL, &client, NULL);
}*/
//pthread_join(s, NULL);
pthread_join(c, NULL);
return 0;
}
FILE = service2.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define PORT_SERV 4442
#define PORT_CLI 4443
time_t t;
time_t t2;
static void * server(){
int sockfd, ret;
struct sockaddr_in serverAddr;
int newSocket;
struct sockaddr_in newAddr;
char buffer[256];
pid_t childpid;
socklen_t addr_size;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("[-] Error in Client Socket\n");
fflush(stdout);
exit(1);
}
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT_SERV);
serverAddr.sin_addr.s_addr = inet_addr("image1");
ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if (ret < 0) {
printf("[-] Error in binding\n");
fflush(stdout);
exit(1);
}
printf("[+] Bind to port %d\n", PORT_CLI);
fflush(stdout);
if (listen(sockfd, 10) == 0) {
printf("[+] Listening...\n");
fflush(stdout);
} else {
printf("[-] Error in binding\n");
fflush(stdout);
}
while(1)
{
newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size);
if(newSocket < 0) {
exit(1);
}
printf("Connection accepted from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
fflush(stdout);
if ((childpid = fork()) == 0)
{
close(sockfd);
while (1)
{
time(&t2);
recv(newSocket, buffer, 256, 0);
if(strcmp(buffer, ": exit") == 0){
printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
fflush(stdout);
break;
} else {
printf("%sClient : %s\n", ctime(&t2), buffer);
fflush(stdout);
send(newSocket, buffer, strlen(buffer), 0);
bzero(buffer, sizeof(buffer));
}
}
}
}
close(newSocket);
}
static void * client(){
int clientSocket, ret;
struct sockaddr_in serverAddr;
char buffer[256];
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket < 0) {
printf("[-] Error in connection\n");
fflush(stdout);
exit(1);
}
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT_CLI);
serverAddr.sin_addr.s_addr = inet_addr("image3");
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
while (ret < 0) {
printf("[-] Erreur de connexion. Nouvelle tentative !\n");
fflush(stdout);
sleep(3);
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
}
printf("[+] Connected to Server.\n");
while(1){
time(&t);
strcpy(buffer, "Bonjour depuis le service 2");
sleep(5);
send(clientSocket, buffer, strlen(buffer), 0);
if (strcmp(buffer, ": exit") == 0) {
printf("[Client -] Disconnected from server.\n");
fflush(stdout);
exit(1);
}
if (recv(clientSocket, buffer, 256, 0) < 0) {
printf("[Client -] Error in receiving data. \n");
fflush(stdout);
} else {
printf("%sService 2: %s \n", ctime(&t), buffer);
fflush(stdout);
}
}
}
int main(void){
pthread_t s, c;
int ret = 0;
ret = pthread_create(&s, NULL, &server, NULL);
if (! ret) {
ret = pthread_create(&c, NULL, &client, NULL);
}
pthread_join(s, NULL);
pthread_join(c, NULL);
return 0;
}
FILE = service3.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define PORT_SERV 4444
//#define PORT_CLI 4443
time_t t;
time_t t2;
static void * server(){
printf("Hello World!\n");
int sockfd, ret;
struct sockaddr_in serverAddr;
int newSocket;
struct sockaddr_in newAddr;
char buffer[256];
pid_t childpid;
socklen_t addr_size;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("[-] Error in connection\n");
exit(1);
}
printf("[+] Client Socket is created !\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT_SERV);
serverAddr.sin_addr.s_addr = inet_addr("image2");
ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if (ret < 0) {
printf("[-] Error in binding\n");
exit(1);
}
printf("[+] Bind to port %d\n", 4444);
if (listen(sockfd, 10) == 0) {
printf("[+] Listening...\n");
} else {
printf("[-] Error in binding\n");
}
while(1)
{
newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size);
if(newSocket < 0) {
exit(1);
}
printf("Connection accepted from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
fflush(stdout);
if ((childpid = fork()) == 0)
{
close(sockfd);
while (1)
{
time(&t2);
recv(newSocket, buffer, 256, 0);
if(strcmp(buffer, ": exit") == 0){
printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
break;
} else {
printf("%sClient : %s\n", ctime(&t2), buffer);
send(newSocket, buffer, strlen(buffer), 0);
bzero(buffer, sizeof(buffer));
}
}
}
}
close(newSocket);
}
int main(void){
printf("Hello World!\n");
fflush(stdout);
pthread_t s;
//pthread_t c;
int ret = 0;
printf("Thread du server\n");
ret = pthread_create(&s, NULL, &server, NULL);
/*if (! ret) {
printf("Thread du client\n");
ret = pthread_create(&c, NULL, &client, NULL);
}*/
pthread_join(s, NULL);
//pthread_join(c, NULL);
return 0;
}
File = docker-compose.yml
version: "3.8"
services:
image1:
build: ./image1
image: service1:1.0
networks:
- mynet
ports:
- 127.0.0.1:4441:4441
image2:
build: ./image2
image: service2:1.0
networks:
- mynet
ports:
- 127.0.0.1:4442:4442
image3:
build: ./image3
image: service3:1.0
networks:
- mynet
ports:
- 127.0.0.1:4443:4443
networks:
mynet:
I build and run with docker compose build docker compose up -d and the images don't connect toghether.
Thanks !
Related
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]){
int portno;
int sockfd, ret;
struct sockaddr_in serverAddr;
int newSocket;
struct sockaddr_in newAddr;
socklen_t addr_size;
char buffer[1024];
pid_t childpid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
printf("[-]Error in connection.\n");
exit(1);
}
printf("[+]Server Socket is created.\n");
portno = atoi(argv[1]);
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(portno);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("[-]Error in binding.\n");
exit(1);
}
printf("[+]Bind to port %d\n", portno);
if(listen(sockfd, 10) == 0){
printf("[+]Listening....\n");
}else{
printf("[-]Error in binding.\n");
}
while(1){
newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size);
if(newSocket < 0){
exit(1);
}
printf("[+]Bind to port %d\n", portno);
if(listen(sockfd, 10) == 0){
printf("[+]Listening....\n");
}else{
printf("[-]Error in binding.\n");
}
while(1){
newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size);
if(newSocket < 0){
exit(1);
}
printf("Connection accepted from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
if((childpid = fork()) == 0){
close(sockfd);
while(1){
recv(newSocket, buffer, 1024, 0);
if(strcmp(buffer, "END") == 0){
printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
break;
}else{
printf("Client: %s\n", buffer);
send(newSocket, buffer, strlen(buffer), 0);
bzero(buffer, sizeof(buffer));
}
}
}
}
close(newSocket);
return 0;
}
}
Client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]){
int portno;
int clientSocket, ret;
struct sockaddr_in serverAddr;
char buffer[1024];
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if(clientSocket < 0){
printf("[-]Error in connection.\n");
exit(1);
}
printf("[+]Client Socket is created.\n");
portno = atoi(argv[2]);
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(portno);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("[-]Error in connection.\n");
exit(1);
}
printf("[+]Connected to Server.\n");
while(1){
printf("Client: \t");
scanf("%s", &buffer[0]);
send(clientSocket, buffer, strlen(buffer), 0);
if(strcmp(buffer, "END") == 0){
close(clientSocket);
printf("[-]Disconnected from server.\n");
exit(1);
}
if(recv(clientSocket, buffer, 1024, 0) < 0){
printf("[-]Error in receiving data.\n");
}else{
printf("Server: \t%s\n", buffer);
}
}
return 0;
}
And i want each time i run server and client, when i run command ls from server take the output from client and other commands too like ls-l and ls -l | wc and ls > result.txt
I try running many examples i found but nothing just running command from server and take the same output to my client
I have code for a server that can handle multiple clients. The client program can connect to the server and issue Unix commands such as ls, date, clear, etc. I have two problems that I cannot figure out. 1) When I initially type ls as an argument it will return some weird garbage, and then if I do ls again then it starts working properly. So only in the beginning, it will give me garbage. 2) When I type the argument 'ps -ael' into the terminal, it will work properly, but then after that I get a 'Failed' message, which is coming from the Client code, specifically at the while(1) loop where if (send(clientSocket, s, echolen, 0) != echolen), this is where the error is occurring. I was curious to know if someone could point to what the problem could be, I think it might be because I create a char array that's too big but I'm not sure.
Client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 4444
#define BUFFSIZE 2048
int main(int argc, char *argv[]){
int clientSocket, ret, portnum;
struct sockaddr_in serverAddr;
int received = 0;
unsigned int echolen;
char buffer[1024];
if(argc < 3){
fprintf(stderr,"usage %s <server-ip-addr> <server-port>\n", argv[0]);
exit(0);
}
portnum = atoi(argv[2]);
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if(clientSocket < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Client Socket is created.\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
// memset(&buffer, '\0', sizeof(buffer));
// serverAddr.sin_family = AF_INET;
// serverAddr.sin_port = htons(PORT);
// serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
// bzero((char *) &serverAddr, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
if(!inet_aton(argv[1], &serverAddr.sin_addr)){
fprintf(stderr, "Error invalid server IP address\n");
exit(1);
}
serverAddr.sin_port = htons(portnum);
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Connected to server.\n");
char s[100];
while(1){
fgets(s, 100, stdin);
s[strlen(s)-1]='\0';
echolen = strlen(s);
/* send() from client; */
if (send(clientSocket, s, echolen, 0) != echolen)
{
printf("Failed");
}
if(strcmp(s,"exit") == 0) // check if exit is typed
exit(0);
fprintf(stdout, "Message from server: ");
while (received < echolen)
{
int bytes = 0;
/* recv() from server; */
if ((bytes = recv(clientSocket, buffer, echolen, 0)) < 1)
{
printf("Failed to get Information");
}
received += bytes;
buffer[bytes] = '\0';
fprintf(stdout, buffer);
}
int bytes = 0;
do {
buffer[bytes] = '\0';
printf("%s\n", buffer);
} while((bytes = recv(clientSocket, buffer, BUFFSIZE-1, 0))>=BUFFSIZE-1);
buffer[bytes] = '\0';
printf("%s\n", buffer);
printf("\n");
}
}
Server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 4444
#define BUFFSIZE 2048
#define MAX 2048
void setup(char inputBuffer[], char *args[], int *background){
const char s[4] = " \t\n";
char *token;
token = strtok(inputBuffer, s);
int i = 0;
while(token != NULL){
args[i] = token;
i++;
token = strtok(NULL, s);
}
args[i] = NULL;
}
void HandleClient(int sock){
char buffer[BUFFSIZE];
int received = -1;
char data[MAX];
memset(data, 0, MAX);
while(1){
data[0] = '\0';
if((received = recv(sock, buffer, BUFFSIZE, 0)) < 0){
printf("Error");
}
buffer[received] = '\0';
strcat(data, buffer);
if(strcmp(data, "exit") == 0){
exit(0);
}
puts(data);
char *args[100];
setup(data, args, 0);
int pipefd[2], length;
if(pipe(pipefd)){
printf("failed to create pipe");
}
pid_t pid = fork();
char path[MAX];
if(pid==0)
{
close(pipefd[0]); // close the readonly side of the pipe
//close(1); // close the original stdout
dup2(pipefd[1],1); // duplicate pipfd[1] to stdout
dup2(pipefd[1], fileno(stderr));
//close(pipefd[0]); // close the readonly side of the pipe
close(pipefd[1]); // close the original write side of the pipe
printf("before execvp");
execvp(args[0],args); // finally execute the command
// exit(0);
}
else
if(pid>0)
{
close(pipefd[1]);
memset(path,'\0',MAX);
while(length=read(pipefd[0],path,MAX-1)){
//printf("Data read so far %s\n", path);
if(send(sock,path,strlen(path),0) != strlen(path) ){
printf("Failed");
}
fflush(NULL);
//printf("Data sent so far %s\n", path);
memset(path,0,MAX);
}
close(pipefd[0]);
//exit(1); removed so server will not terminate
}
else
{
printf("Error !\n");
exit(0);//
}
}
}
int main(){
int sockfd, ret;
struct sockaddr_in serverAddr;
int newSocket;
struct sockaddr_in newAddr;
socklen_t addr_size;
char buffer[1024];
pid_t childpid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
printf("Error in connection.\n");
exit(1);
}
printf("Server Socket is created.\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("Error in binding");
exit(1);
}
printf("Bind to port %d\n", 4444);
if(listen(sockfd, 10) == 0){
printf("Listening....\n");
}else{
printf("Error in binding.\n");
}
while(1){
newSocket = accept(sockfd, (struct sockaddr*) &newAddr, &addr_size);
if(newSocket < 0){
exit(1);
}
printf("Connection accepted from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
//worker
if((childpid = fork()) == 0){
close(sockfd);
while(1){
recv(newSocket, buffer, 1024, 0);
if(strcmp(buffer, ":exit") == 0){
printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
break;
}else{
printf("Client: %s\n", buffer);
send(newSocket, buffer, strlen(buffer), 0);
bzero(buffer, sizeof(buffer));
}
HandleClient(newSocket);
}
}
}
close(newSocket);
return 0;
}
I want to create a simple multithreaded chat application in C using api. For the beginning, i wrote a simple server communicating with client but there is a problem in the order messages sent.
example output:
in server
*new_sock socket number: 4
Server:hello client
Client:hello server
Server:how are you?
Client:
Server:
in client
Server:hello client
Client:hello server
Server:how are you?
Client:
//server code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <pthread.h>
void* connection_handler(void* socket_descriptor)
{
int socket = *(int *)socket_descriptor;
int n;
char server_buffer[256];
memset(server_buffer, 0, sizeof(server_buffer));
printf("Server:");
gets(server_buffer);
send(socket, server_buffer, strlen(server_buffer), 0);
memset(server_buffer, 0, sizeof(server_buffer));
while ((n = recv(socket, server_buffer, 255, 0)) > 0)
{
server_buffer[n] = '\0';
printf("Client:%s\n", server_buffer);
memset(server_buffer, 0, sizeof(server_buffer));
printf("Server:");
gets(server_buffer);
send(socket, server_buffer, strlen(server_buffer), 0);
memset(server_buffer, 0, sizeof(server_buffer));
n = 0;
}
close(socket);
free(socket_descriptor);
return 0;
}
int main(int argc, char *argv[])
{
int server_sock, client_sock, portno, client_len, n;
int *new_sock;
struct sockaddr_in server_addr, client_addr;
if(argc < 2)
{
printf("ERROR: no port provided.\n");
exit(1);
}
server_sock = socket(AF_INET, SOCK_STREAM, 0);
if(server_sock < 0)
{
printf("ERROR: opening socket.");
exit(1);
}
portno = atoi(argv[1]);
memset((char *)&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(portno);
server_addr.sin_addr.s_addr = INADDR_ANY;
if( bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0 )
{
printf("ERROR: binding socket.");
exit(1);
}
listen(server_sock, 5);
pthread_t handler_thread;
while( client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_len) )
{
new_sock = malloc(sizeof(int));
*new_sock = client_sock;
printf("*new_sock socket number: %d\n", *new_sock);
if( pthread_create(&handler_thread, (void *)NULL, connection_handler, (void *)new_sock) < 0)
{
printf("ERROR: creating thread\n");
exit(1);
}
}
pthread_join(handler_thread, NULL);
printf("server shut down.\n");
return 0;
}
//client code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int main(int argc, char* argv[])
{
int sock_descriptor, portno, n;
struct sockaddr_in server_addr;
char buffer[256];
if (argc != 2)
{
printf("usage: %s port\n", argv[0]);
exit(1);
}
portno = atoi(argv[1]);
sock_descriptor = socket(AF_INET, SOCK_STREAM, 0);
if (sock_descriptor < 0)
{
printf("ERROR: creating socket!\n");
exit(1);
}
memset((char *)&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(portno);
if (connect(sock_descriptor, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
printf("ERROR: connecting server!\n");
exit(1);
}
memset(buffer, 0, sizeof(buffer));
while((n = recv(sock_descriptor, buffer, 255, 0)) > 0)
{
buffer[n] = '\0';
printf("Server:%s\n", buffer);
memset(buffer, 0, sizeof(buffer));
printf("Client:");
gets(buffer);
send(sock_descriptor, buffer, sizeof(buffer), 0);
memset(buffer, 0, sizeof(buffer));
}
if (n <= 0)
{
printf("ERROR: reading from socket");
exit(1);
}
return 0;
}
Join the threads right after it has been created , accept is a blocking call (I assume you have not modified the default behavior) . Threads are complex to analyze however , the call to join wont even come since blocking accept call in while loop.
while(1)
{
//do something here
...
if( pthread_create(&handler_thread, (void *)NULL, connection_handler, (void *)new_sock) < 0)
{
printf("ERROR: creating thread\n");
exit(1);
}
pthread_join(handler_thread, NULL); //Use it right after creating thread
}
I'm trying to make two-way communication over a TCP socket between server and client on Windows. I've tried using threads, but it doesn't work, and I don't know why.
If I try putting this in the while loop, it waits for the user to type something (because of fgets()) before it prints the next message.
while(1) {
bzero(message, 2000);
if (recv(sock, message, 2000, 0) < 0) {
printf("Connection lost!\n");
getch();
}
else {
strcat(message, "\0");
fprintf(stdout, "%s", message);
};
bzero(client, 2000);
fgets(sednmesg, sizeof(sednmesg), stdin);
strcat(client, sednmesg);
strcat(client, "\0");
send(sock, client, strlen(client), 0);
}
My disastrous attempt with threads:
Server.c:
#include <stdio.h>
#include <winsock.h>
#include <stdlib.h>
#include "stdafx.h"
#include <conio.h>
#include <io.h>
#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
#pragma comment(lib,"ws2_32.lib") //Winsock Library
char message[4040];
DWORD WINAPI thrd() {
WSADATA wsa;
SOCKET sock, newsock;
int c;
struct sockaddr_in server, client;
char smesg[155];
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
printf("Initialised.\n");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
printf("Could not create socket! Error: %d", WSAGetLastError());
return 1;
}
//textcolor(2);
printf("Socket Created!\n");
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8989);
//bind
if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed! Error Code: %d", WSAGetLastError());
}
puts("Binded!");
printf("\nNow Listening...\n");
listen(sock, 1);
//Accept!
c = sizeof(struct sockaddr_in);
newsock = accept(sock, (struct sockaddr *)&client, &c);
if (newsock == INVALID_SOCKET) {
printf("Couldn't Accept connection!");
}
printf("Accepted Connection!\n");
u_long iMode = 1;
ioctlsocket(newsock, FIONBIO, &iMode);
Sleep(99);
system("cls");
printf("Writer Thread has been started!");
//char *client_ip = inet_ntoa(client.sin_addr);
//int client_port = ntohs(client.sin_port);
while (1) {
bzero(smesg, sizeof(smesg));
fgets(smesg, sizeof(smesg), stdin);
strcat(smesg, "\0");
send(newsock, smesg, strlen(smesg), 0);
}
}
int main()
{
WSADATA wsa;
FILE * fp;
unsigned long on = 1;
const char *file = "fout.txt";
SOCKET sock, newsock;
int c;
struct sockaddr_in server, client;
char smesg[155];
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
printf("Initialised.\n");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
printf("Could not create socket! Error: %d", WSAGetLastError());
return 1;
}
//textcolor(2);
printf("Socket Created!\n");
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(3939);
//bind
if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed! Error Code: %d", WSAGetLastError());
}
puts("Binded!");
printf("\nNow Listening...\n");
listen(sock, 1);
//Accept!
c = sizeof(struct sockaddr_in);
newsock = accept(sock, (struct sockaddr *)&client, &c);
ioctlsocket(newsock, FIONBIO, &on);
if (newsock == INVALID_SOCKET) {
printf("Couldn't Accept connection!");
}
printf("Accepted Connection!\n");
//char *client_ip = inet_ntoa(client.sin_addr);
//int client_port = ntohs(client.sin_port);
HANDLE thread = CreateThread(NULL, 0, thrd, NULL, 0, NULL);
fp = fopen(file, "r+");
while (1) {
/*
bzero(smesg, sizeof(smesg));
printf("Command: ");
fgets(smesg, 155, stdin);
strcat(smesg, "\0");
send(newsock, smesg, strlen(smesg), 0);
*/
bzero(message, sizeof(message));
recv(newsock, message, 2000, 0);
fprintf(stdout, "%s", message);
fprintf(fp, "%s", message);
}
fclose(fp);
return 0;
}
Client.c:
#include <stdio.h>
#include <winsock.h>
#include <stdlib.h>
#include "stdafx.h"
#include <conio.h>
#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
#pragma comment(lib,"ws2_32.lib") //Winsock Library
DWORD WINAPI thrd() {
char client[2050] = "Client: ";
WSADATA wsa;
SOCKET sock;
struct sockaddr_in server;
char sednmesg[2000];
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
getch();
return 1;
}
printf("Initialised.\n");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
printf("Could not create socket! Error: %d", WSAGetLastError());
getch();
return 1;
}
//textcolor(2);
printf("Socket Created!\n");
//ioctlsocket(sock, FIONBIO, &on);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(8989);
//Connect
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
puts("Connect Error");
getch();
return 1;
}
puts("Connected\n");
// If iMode!=0, non-blocking mode is enabled.
u_long iMode = 1;
ioctlsocket(sock, FIONBIO, &iMode);
Sleep(99);
system("cls");
printf("Writer Thread has been started!");
//We'll be running this one on port 8989 if this doesn't work!
while (1) {
bzero(client, 2000);
fgets(sednmesg, sizeof(sednmesg), stdin);
strcat(client, sednmesg);
strcat(client, "\0");
send(sock, client, strlen(client), 0);
}
}
int main(int argc, char *argv[])
{
char *msg = "a";
char client[2050] = "Client: ";
unsigned long on = 1;
int reader;
WSADATA wsa;
int sent = 0;
SOCKET sock;
struct sockaddr_in server;
char message[2000];
char sednmesg[2000];
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
getch();
return 1;
}
printf("Initialised.\n");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
printf("Could not create socket! Error: %d", WSAGetLastError());
getch();
return 1;
}
//textcolor(2);
printf("Socket Created!\n");
//ioctlsocket(sock, FIONBIO, &on);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(3939);
//Connect
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
puts("Connect Error");
getch();
return 1;
}
puts("Connected\n");
// If iMode!=0, non-blocking mode is enabled.
u_long iMode = 1;
ioctlsocket(sock, FIONBIO, &iMode);
//Creating writer thread.
HANDLE thread = CreateThread(NULL, 0, thrd, NULL, 0, NULL);
while (1) {
bzero(message, 2000);
if (recv(sock, message, 2000, 0) < 0) {
printf("Connection lost!\n");
getch();
}
else {
strcat(message, "\0");
fprintf(stdout, "%s", message);
};
//bzero(client, 2000);
/*
fgets(sednmesg, sizeof(sednmesg), stdin);
strcat(client, sednmesg);
strcat(client, "\0");
send(sock, client, strlen(client), 0);
*/
}
return 0;
}
You don't need to open/connect 2 separate listening ports in order to implementing bi-directional communication. TCP is bi-directional, you only need one connection. However, you are enabling non-blocking socket I/O on both ends, but you are not actually using non-blocking I/O correctly. In particular, you are not handling the WSAEWOULDBLOCK error code at all, which is reported by recv() when there is no data available to read, and by send() when the receiver has too much data to read and cannot receive new data yet.
If you want to use threads, then use separate threads for reading and sending, and forget non-blocking I/O altogether. But make sure you are defining your threads correctly (you thread procedure is missing a required input parameter!).
Try something more like this:
Server.c:
#include "stdafx.h"
#include <stdio.h>
#include <winsock.h>
#include <stdlib.h>
#include <conio.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
DWORD WINAPI sendThrd(LPVOID lpParam)
{
SOCKET sock = * (SOCKET*) lpParam;
char smesg[155], *pdata;
int len, ret;
do
{
if (!fgets(smesg, sizeof(smesg), stdin))
break;
len = strlen(smesg);
pdata = smesg;
while (len > 0)
{
ret = send(sock, pdata, len, 0);
if (ret == SOCKET_ERROR)
{
printf("Send failed. Error: %d", WSAGetLastError());
break;
}
pdata += ret;
len -= ret;
}
}
while (true);
shutdown(sock, SD_SEND);
return 0;
}
DWORD WINAPI recvThrd(LPVOID lpParam)
{
SOCKET sock = * (SOCKET*) lpParam;
char smesg[256];
int ret;
FILE *fp = fopen("fout.txt", "w+");
do
{
ret = recv(sock, smesg, sizeof(smesg), 0);
if (ret <= 0)
{
if (ret == 0)
printf("Client disconnected\n");
else
printf("Connection lost! Error: %d\n", WSAGetLastError());
break;
}
printf("%.*s", ret, smesg);
if (fp)
fprintf(fp, "%.*s", ret, smesg);
}
while (true);
if (fp)
fclose(fp);
shutdown(sock, SD_RECEIVE);
return 0;
}
int main()
{
WSADATA wsa;
SOCKET sock, newsock;
int c;
struct sockaddr_in server;
printf("Initializing Winsock...\n");
int ret = WSAStartup(MAKEWORD(2, 2), &wsa);
if (ret != 0)
{
printf("Initialization Failed. Error: %d", ret);
return 1;
}
printf("Initialized.\n");
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
printf("Could not create socket! Error: %d\n", WSAGetLastError());
return 1;
}
//textcolor(2);
printf("Socket Created!\n");
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(3939);
//bind
if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Bind failed! Error: %d\n", WSAGetLastError());
closesocket(sock);
return 1;
}
printf("Binded!\n");
// listen
if (listen(sock, 1) == SOCKET_ERROR) {
printf("Listen failed! Error: %d\n", WSAGetLastError());
closesocket(sock);
return 1;
}
printf("Now Listening...\n");
//Accept!
c = sizeof(client);
newsock = accept(sock, (struct sockaddr *)&client, &c);
if (newsock == INVALID_SOCKET) {
printf("Couldn't Accept connection! Error: %d\n", WSAGetLastError());
closesocket(sock);
return 1;
}
//char *client_ip = inet_ntoa(client.sin_addr);
//int client_port = ntohs(client.sin_port);
printf("Accepted Connection!\n");
printf("Starting Reader/Writer Threads...\n");
HANDLE threads[2];
threads[0] = CreateThread(NULL, 0, sendThrd, &newsock, 0, NULL);
threads[1] = CreateThread(NULL, 0, recvThrd, &newsock, 0, NULL);
WaitForMultipleObjects(2, threads, TRUE, INFINITE);
CloseHandle(threads[0]);
CloseHandle(threads[1]);
closesocket(newsock);
closesocket(sock);
return 0;
}
Client.c:
#include "stdafx.h"
#include <stdio.h>
#include <winsock.h>
#include <stdlib.h>
#include <conio.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
DWORD WINAPI sendThrd(LPVOID lpParam)
{
SOCKET sock = * (SOCKET*) lpParam;
char smesg[155], *pdata;
int len, ret;
do
{
if (!fgets(smesg, sizeof(smesg), stdin))
break;
len = strlen(smesg);
pdata = smesg;
while (len > 0)
{
ret = send(sock, pdata, len, 0);
if (ret == SOCKET_ERROR)
{
printf("Send failed. Error: %d\n", WSAGetLastError());
break;
}
pdata += ret;
len -= ret;
}
}
while (true);
shutdown(sock, SD_SEND);
return 0;
}
DWORD WINAPI recvThrd(LPVOID lpParam)
{
SOCKET sock = * (SOCKET*) lpParam;
char smesg[256];
int ret;
do
{
ret = recv(sock, smesg, sizeof(smesg), 0);
if (ret <= 0)
{
if (ret == 0)
printf("Server disconnected\n");
else
printf("Connection lost! Error: %d\n", WSAGetLastError());
break;
}
printf("%.*s", ret, smesg);
}
while (true);
shutdown(sock, SD_RECEIVE);
return 0;
}
int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET sock;
struct sockaddr_in server;
printf("Initializing Winsock...\n");
int ret = WSAStartup(MAKEWORD(2, 2), &wsa);
if (ret != 0)
{
printf("Initialization Failed. Error: %d", ret);
return 1;
}
printf("Initialized.\n");
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
printf("Could not create socket! Error: %d", WSAGetLastError());
getch();
return 1;
}
//textcolor(2);
printf("Socket Created!\n");
memset(&server, 0, sizeof(server));
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(3939);
//Connect
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR) {
printf("Connect failed! Error: %d", WSAGetLastError());
closesocket(sock);
getch();
return 1;
}
printf("Connected\n");
//Creating reader/writer threads.
printf("Starting Reader/Writer Threads...\n");
HANDLE threads[2];
threads[0] = CreateThread(NULL, 0, sendThrd, &sock, 0, NULL);
threads[1] = CreateThread(NULL, 0, recvThrd, &sock, 0, NULL);
WaitForMultipleObjects(2, threads, TRUE, INFINITE);
CloseHandle(threads[0]);
CloseHandle(threads[1]);
closesocket(sock);
getch();
return 0;
}
I am attempting to write a simple chat program where one user can connect to a host. The two should be able to talk to each other (they might interrupt each other but that is ok). I am having difficulties with select(). Here is the code:
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 <arpa/inet.h>
#define MAXDATASIZE 1024 // max number of bytes we can get at once
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa) {
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*) sa)->sin_addr);
}
return &(((struct sockaddr_in6*) sa)->sin6_addr);
}
int main(int argc, char *argv[]) {
int sockfd, numbytes;
char buf[MAXDATASIZE];
char buffer[1024];
char *buff;
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
char *port;
int num;
struct timeval tv;
//select data
fd_set rfds;
fd_set wfds;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
if (argc != 2) {
fprintf(stderr, "usage: client port\n");
exit(1);
}
port = argv[1];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo("localhost", port, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and connect to the first we can
for (p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("client: socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("client: connect");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "client: failed to connect\n");
return 2;
}
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *) p->ai_addr),
s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(servinfo); // all done with this structure
FD_SET(sockfd, &rfds);
FD_SET(sockfd, &wfds);
if (select(sockfd + 1, &rfds, &wfds, NULL, &tv) < 0) {
perror("select");
return -1;
}
if (FD_ISSET(sockfd, &wfds)) {
while (1) {
fgets(buffer, MAXDATASIZE - 1, stdin);
if ((send(sockfd, buffer, strlen(buffer), 0)) == -1) {
fprintf(stderr, "Failure Sending Message\n");
close(sockfd);
exit(1);
} else {
printf("Message being sent: %s\n", buffer);
break;
}
}
}
if (FD_ISSET(sockfd, &rfds)) {
while (1) {
if ((num = recv(sockfd, buffer, 10240, 0)) == -1) {
//fprintf(stderr,"Error in receiving message!!\n");
perror("recv");
exit(1);
} else if (num == 0) {
printf("Connection closed\n");
return 0;
}
// num = recv(client_fd, buffer, sizeof(buffer),0);
buffer[num] = '\0';
printf("Message received: %s\n", buffer);
break;
}
}
close(sockfd);
return 0;
}
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 <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define BACKLOG 10 // how many pending connections queue will hold
#define MAXDATASIZE 100 // max number of bytes we can get at once
void sigchld_handler(int s) {
while (waitpid(-1, NULL, WNOHANG) > 0);
}
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa) {
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*) sa)->sin_addr);
}
return &(((struct sockaddr_in6*) sa)->sin6_addr);
}
int main(int argc, char *argv[]) {
int sockfd; // set up socket
int new_sockfd; // new socket after connection
struct addrinfo hints, *results, *p;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes = 1;
char s[INET6_ADDRSTRLEN];
int rv;
int i;
struct timeval tv;
int num;
char buffer[10241];
int nsock;
char buf[MAXDATASIZE];
int numbytes;
char *port;
//select data
fd_set rfds;
fd_set wfds;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
/* validate command-line arguments */
if (argc != 2) {
fprintf(stderr, "Usage: %s port\n", argv[0]);
exit(1);
}
tv.tv_sec = 100;
tv.tv_usec = 0;
/* only argument to port number (./sc [port])*/
port = argv[1];
bzero(&hints, sizeof (struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // any IP
if ((rv = getaddrinfo(NULL, port, &hints, &results)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for (p = results; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("1: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof (int)) == -1) {
perror("setsockopt");
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "server: failed to bind\n");
return 2;
}
freeaddrinfo(results); // all done with this structure
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections...\n");
while (1) { // main accept() loop
sin_size = sizeof their_addr;
new_sockfd = accept(sockfd, (struct sockaddr *) &their_addr, &sin_size);
if (new_sockfd == -1) {
perror("accept");
continue;
}
//get the clients info
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *) &their_addr),
s, sizeof s);
printf("server: got connection from %s\n", s);
FD_SET(new_sockfd, &rfds);
FD_SET(new_sockfd, &wfds);
if (select(new_sockfd + 1, &rfds, &wfds, NULL, &tv) < 0) {
perror("select");
return -1;
}
if (FD_ISSET(new_sockfd, &rfds))
while (1) {
if ((num = recv(new_sockfd, buffer, 10240, 0)) == -1) {
//fprintf(stderr,"Error in receiving message!!\n");
perror("recv");
exit(1);
} else if (num == 0) {
printf("Connection closed\n");
return 0;
}
// num = recv(client_fd, buffer, sizeof(buffer),0);
buffer[num] = '\0';
printf("Message received: %s\n", buffer);
break;
}
if (FD_ISSET(new_sockfd, &wfds))
while (1) {
fgets(buffer, MAXDATASIZE - 1, stdin);
if ((send(new_sockfd, buffer, strlen(buffer), 0)) == -1) {
fprintf(stderr, "Failure Sending Message\n");
close(new_sockfd);
exit(1);
} else {
printf("Message being sent: %s\n", buffer);
break;
}
}
} //Outer While
close(new_sockfd); // parent doesn't need this
return 0;
}
The host and client aren't able to communicate. Can anyone tell me where the issue is?
You need to call select() inside of the loops, not outside. Also, you have to reset the fd_set and timeval structs each time you call select().