C: TCP server could not receive message from client - c

I am a C beginner. I want to send a file by TCP. The client reads content from a txt file and sent it to server. Read method is ok. It reads the specified bytes from the file. Send method dose not throw any exception. However the server receives nothing. I try to solve it for a whole day. I fail.
Please help me check what is wrong with my code.
As comment advice, I edit my code again. Now there are two problem. One is that in the client loop the return values from client fread() and send() is greater than 0 for the first two times while the server accept() is still blcoked without getting message from client.
The second problem. In the third client loop, the return value of client fread() is still greater than 0, but the return value of send() is -1.I try to open the file in binary mode rb instead of r. It is the same problem.
the edited client code:
#include <stdio.h>
#include <winsock.h>
#include <time.h>
#pragma comment(lib, "WS2_32.lib")
#define MAXLINE 1024*4
SOCKET sockClient;// = socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN servAddr;
int main(void) {
WSADATA wsd;
FILE *fp;
int read_len;
char buf2[MAXLINE];
time_t t_start, t_end;
if ((fp = fopen("file.txt", "r")) == NULL) {
perror("Open file failed\n");
exit(0);
}
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
printf("WSAStartup failed !\n");
return 1;
}
sockClient = socket(AF_INET, SOCK_STREAM, 0);
servAddr.sin_family = AF_INET;
servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
servAddr.sin_port = htons(5000);
/* connect the server commanted by guoqingbo*/
int i_ret = connect(sockClient, (struct sockaddr *) &servAddr, sizeof(struct sockaddr));
if (-1 == i_ret) {
perror("Connect socket failed!\n");
exit(0);
}
printf("client starts\n");
t_start = time(NULL);
while (1) {
read_len = fread(buf2, sizeof(char), MAXLINE, fp);
if (read_len < 0) {
perror("read data failed\n");
break;
} else if (read_len == 0) {
printf("read finished\n");
}
int send_len = send(sockClient, buf2, read_len, 0);
if (send_len < 0) {
perror("Send data failed\n");
exit(0);
} else if (send_len == 0) {
printf("send finished\n");
break;
}
}
t_end = time(NULL);
printf("The time used %f s\n", difftime(t_end, t_start));
fclose(fp);
closesocket(sockClient);
WSACleanup();
return 0;
}
the edited server code:
#include <stdio.h>
#include <WINSOCK2.H>
#include <strings.h>
#include <stdlib.h>
#pragma comment(lib, "WS2_32.lib")
#define BUF_SIZE 1024*4
SOCKET socketSrv;
SOCKADDR_IN addrSrv;
SOCKADDR_IN addrClient;
char buf[BUF_SIZE];
int main(void) {
WSADATA wsd;
int nRet;
int recv_len;
FILE *fp;
if ((fp = fopen("file.txt", "w")) == NULL) {
perror("Creat file failed");
exit(0);
}
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
printf("WSAStartup failed !\n");
return 1;
}
socketSrv = socket(AF_INET, SOCK_STREAM, 0);
int len = sizeof(SOCKADDR);
ZeroMemory(buf, BUF_SIZE);
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(5000);
nRet = bind(socketSrv, (SOCKADDR *) &addrSrv, sizeof(SOCKADDR));
if (SOCKET_ERROR == nRet) {
printf("bind failed !\n");
closesocket(socketSrv);
WSACleanup();
return -1;
}
if (SOCKET_ERROR == listen(socketSrv, 10)) {
printf("Server Listen Failed: %d", WSAGetLastError());
exit(1);
}
printf("server started..\n");
while (1) {
SOCKET m_New_Socket = accept(socketSrv, (SOCKADDR *) &addrClient, &len);
if (SOCKET_ERROR == m_New_Socket) {
printf("Server Accept Failed: %d", WSAGetLastError());
break;
}
if (recv_len = recv(socketSrv, buf, BUF_SIZE, 0) < 0) {
printf("Server Receive Data Failed!");
break;
}
int write_length = fwrite(buf, sizeof(char), recv_len, fp);
if (write_length < recv_len) {
printf("File write failed\n");
break;
}
}
fclose(fp);
closesocket(socketSrv);
WSACleanup();
return 0;
}

Related

openSSL C program

I wrote a program to send the contents of a file between a computer and a raspberry pi 4; on localhost it works but when I try it between the two hosts it does not work.
The output is "Send Success, NumBytes = 7" from the sender part and "Receive Success, NumBytes = 0" from the receiver part.
I created the certificate following this guide: https://www.simba.com/products/SEN/doc/Client-Server_user_guide/content/clientserver/configuringssl/signingca.htm
sender.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "transfer.h"
#include <openssl/ssl.h>
void sendfile(FILE *fp, SSL *ssl);
ssize_t total = 0;
SSL_CTX *ctx;
int main(int argc, char *argv[])
{
SSL *ssl;
if (argc != 3)
{
perror("usage:send_file filepath <IPaddress>");
exit(1);
}
SSL_library_init();
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("Can't allocate sockfd");
exit(1);
}
if ((ctx = SSL_CTX_new(SSLv23_client_method())) == NULL)
{
fprintf(stderr, "ERROR: failed to create SSL_CTX\n");
return -1;
}
SSL_CTX_set_options(ctx,SSL_OP_NO_TLSv1_3);
if (SSL_CTX_load_verify_locations(ctx, "./certs/CA-cert.pem", 0) != 1)
{
fprintf(stderr, "Error loading ./certs/cacert.pem, please check the file.\n");
exit(EXIT_FAILURE);
}
struct sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVERPORT);
if (inet_pton(AF_INET, argv[2], &serveraddr.sin_addr) < 0)
{
perror("IPaddress Convert Error");
exit(1);
}
if (connect(sockfd, (const struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("Connect Error");
exit(1);
}
if ((ssl = SSL_new(ctx)) == NULL)
{
fprintf(stderr, "ERROR: failed to create SSL object\n");
return -1;
}
/* Attach SSL to the socket */
SSL_set_fd(ssl, sockfd);
/* Connect to SSL on the server side */
if (SSL_connect(ssl) < 0)
{
fprintf(stderr, "ERROR: failed to connect to SSL\n");
return -1;
}
char *filename = basename(argv[1]);
if (filename == NULL)
{
perror("Can't get filename");
exit(1);
}
char buff[BUFFSIZE] = {0};
strncpy(buff, filename, strlen(filename));
if (send(sockfd, buff, BUFFSIZE, 0) == -1)
{
perror("Can't send filename");
exit(1);
}
FILE *fp = fopen(argv[1], "rb");
if (fp == NULL)
{
perror("Can't open file");
exit(1);
}
sendfile(fp, ssl);
//puts("Send Success");
printf("Send Success, NumBytes = %d\n", total);
fclose(fp);
close(sockfd);
SSL_free(ssl);
SSL_CTX_free(ctx);
return 0;
}
void sendfile(FILE *fp, SSL *ssl)
{
int n;
char sendline[MAX_LINE] = {0};
while ((n = fread(sendline, sizeof(char), MAX_LINE, fp)) > 0)
{
total += n;
if (n != MAX_LINE && ferror(fp))
{
perror("Read File Error");
exit(1);
}
if (SSL_write(ssl, sendline, strlen(sendline)) <= 0)
{
perror("Can't send file\n");
exit(1);
}
memset(sendline, 0, MAX_LINE);
}
}
receiver.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "transfer.h"
#include <openssl/ssl.h>
void writefile(SSL *ssl, FILE *fp);
ssize_t total = 0;
int main(int argc, char *argv[])
{
SSL_CTX *ctx;
SSL *ssl;
SSL_library_init();
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
perror("Can't allocate sockfd");
exit(1);
}
ctx = SSL_CTX_new(SSLv23_method());
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
if (ctx == NULL)
{
fprintf(stderr, "ERROR: failed to create SSL_CTX\n");
return -1;
}
if (SSL_CTX_load_verify_locations(ctx, "./certs/CA-cert.pem", 0) != 1)
{
fprintf(stderr, "Error loading ./certs/ca-cert.pem, please check the file.\n");
return -1;
}
if (SSL_CTX_use_certificate_file(ctx, "./certs/server-cert.pem", SSL_FILETYPE_PEM) != 1)
{
fprintf(stderr, "Error loading ./certs/servercert.pem, please check the file.\n");
return -1;
}
if (SSL_CTX_use_PrivateKey_file(ctx, "./certs/server-key.pem", SSL_FILETYPE_PEM) != 1)
{
fprintf(stderr, "Error loading ./certs/serverkey.pem, please check the file.\n");
return -1;
}
//SSL_CTX_set_options(ctx,SSL_OP_NO_TICKET);
struct sockaddr_in clientaddr, serveraddr;
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(SERVERPORT);
if (bind(sockfd, (const struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1)
{
perror("Bind Error");
exit(1);
}
if (listen(sockfd, LINSTENPORT) == -1)
{
perror("Listen Error");
exit(1);
}
socklen_t addrlen = sizeof(clientaddr);
int connfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen);
if (connfd == -1)
{
perror("Connect Error");
exit(1);
}
close(sockfd);
if ((ssl = SSL_new(ctx)) == NULL)
{
fprintf(stderr, "ERROR: failed to create SSL object\n");
return -1;
}
SSL_set_fd(ssl, connfd);
/* Establish TLS connection */
int ret = SSL_accept(ssl);
if (ret < 0)
{
fprintf(stderr, "SSL_accept error = %d\n", SSL_get_error(ssl, ret));
return -1;
}
char filename[BUFFSIZE] = {0};
if (recv(connfd, filename, BUFFSIZE, 0) == -1)
{
perror("Can't receive filename");
exit(1);
}
FILE *fp = fopen("output.txt", "wb");
if (fp == NULL)
{
perror("Can't open file");
exit(1);
}
char addr[INET_ADDRSTRLEN];
printf("Start receive file: %s from %s\n", filename, inet_ntop(AF_INET, &clientaddr.sin_addr, addr, INET_ADDRSTRLEN));
writefile(ssl, fp);
printf("Receive Success, NumBytes = %d\n", total);
SSL_free(ssl);
SSL_CTX_free(ctx);
fclose(fp);
close(connfd);
return 0;
}
void writefile(SSL *ssl, FILE *fp)
{
ssize_t n;
char buff[MAX_LINE] = {0};
clock_t t;
t = clock();
while ((n = SSL_read(ssl, buff, sizeof(buff))) > 0)
{
total += n;
if (n == -1)
{
perror("Receive File Error");
exit(1);
}
if (fwrite(buff, sizeof(char), n, fp) != n)
{
perror("Write File Error");
exit(1);
}
memset(buff, 0, MAX_LINE);
}
t = clock() - t;
double time_taken = ((double)t)/CLOCKS_PER_SEC; // in seconds
printf("%f seconds to receive data \n", time_taken);
}
Thanks
The receiver calls recv() on connfd after this file descriptor has been given to the ssl connection, so there is nothing more to be read on the ssl connection.

WINDOWS C: TCP Socket send&recv at the same time

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;
}

Sending to client from server [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm trying to send data from a server to a client whenever the client executes a recv() command. As the code stands right now, I cannot get the client to print any data it receives. I cannot figure out whether something is wrong with my server or client, so any help would be appreciated. Thanks!
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#define ECHO_PORT 9999
#define BUF_SIZE 4096
int main(int argc, char* argv[])
{
if (argc != 3)
{
fprintf(stderr, "usage: %s <server-ip> <port>",argv[0]);
return EXIT_FAILURE;
}
char buf[BUF_SIZE];
int status, sock, sock2;
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
struct addrinfo *servinfo; //will point to the results
hints.ai_family = AF_INET; //IPv4
hints.ai_socktype = SOCK_STREAM; //TCP stream sockets
hints.ai_flags = AI_PASSIVE; //fill in my IP for me
if ((status = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0)
{
fprintf(stderr, "getaddrinfo error: %s \n", gai_strerror(status));
return EXIT_FAILURE;
}
if ((sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1)
{
fprintf(stderr, "Socket failed");
return EXIT_FAILURE;
}
if ((connect(sock, (struct sockaddr *) servinfo->ai_addr, servinfo->ai_addrlen)) != 0)
{
fprintf(stderr, "Connection failed");
return EXIT_FAILURE;
}
if ((sock2 = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1)
{
fprintf(stderr, "Socket failed");
return EXIT_FAILURE;
}
if ((connect(sock2, (struct sockaddr *) servinfo->ai_addr, servinfo->ai_addrlen)) != 0)
{
fprintf(stderr, "Connection failed");
return EXIT_FAILURE;
}
while (1) {
//char msg[BUF_SIZE] = "ashudfshuhafhu";
//char msg[BUF_SIZE];
//fgets(msg, BUF_SIZE, stdin);
//int i = 2;
//if (strlen(msg) == i)
// break;
int bytes_received;
// fprintf(stdout, "Sending %s", msg);
//send(sock, msg , strlen(msg), 0);
if((bytes_received = recv(sock, buf, BUF_SIZE, 0)) > 1)
{
buf[bytes_received] = '\0';
fprintf(stdout, "Received %s", buf);
}
}
freeaddrinfo(servinfo);
close(sock);
return EXIT_SUCCESS;
}
Server.c
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define ECHO_PORT 9999
#define BUF_SIZE 4096
int close_socket(int sock)
{
if (close(sock))
{
fprintf(stderr, "Failed closing socket.\n");
return 1;
}
return 0;
}
int main(int argc, char* argv[])
{
int sock, client_sock;
ssize_t readret;
socklen_t cli_size;
struct timeval tv;
struct sockaddr_in addr, cli_addr;
char buf[BUF_SIZE] = "wetwetwetwetwetwetwetwet";
fd_set readfds, writefds;
fd_set activereadfds, activewritefds;
cli_size = sizeof(&cli_addr);
tv.tv_sec = 5;
tv.tv_usec = 0;
fprintf(stdout, "----- Echo Server -----\n");
/* all networked programs must create a socket */
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
fprintf(stderr, "Failed creating socket.\n");
return EXIT_FAILURE;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(ECHO_PORT);
addr.sin_addr.s_addr = INADDR_ANY;
/* servers bind sockets to ports---notify the OS they accept connections */
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)))
{
close_socket(sock);
fprintf(stderr, "Failed binding socket.\n");
return EXIT_FAILURE;
}
if (listen(sock, 5))
{
close_socket(sock);
fprintf(stderr, "Error listening on socket.\n");
return EXIT_FAILURE;
}
FD_ZERO(&readfds);
FD_SET(sock, &activereadfds);
while (1)
{
fprintf(stdout,"in here.\n");
readfds = activereadfds;
writefds = activewritefds;
FD_ZERO(&activereadfds);
FD_ZERO(&activewritefds);
if (select(51, &readfds, &writefds, NULL, &tv) < 0)
{
perror("select");
return EXIT_FAILURE;
}
for (int i = 0; i < 10; ++i)
{
if (FD_ISSET (i, &readfds))
{
if (i == sock)
{
fprintf(stdout, "main loop. \n");
client_sock = accept(sock,
(struct sockaddr *) &cli_addr, &cli_size);
FD_SET(client_sock, &activereadfds);
FD_SET(client_sock, &activewritefds);
if (client_sock < 0)
{
perror("accept");
return EXIT_FAILURE;
}
} else {
fprintf(stdout, "second loop \n");
readret = send(i,buf, strlen(buf),0);
if (readret < 0)
fprintf(stdout, "yay");
}
}
if (FD_ISSET(i, &writefds))
{ fprintf(stdout, "ugh \n");
readret = send(i,buf,BUF_SIZE,0);
//if (readret > 0)
//while((readret = recv(i, buf, BUF_SIZE, 0)) >= 1)
// {
//if (send(i, buf, readret, 0) != readret)
//{
// close_socket(i);
// close_socket(sock);
// fprintf(stderr, "Error sending to client.\n");
// return EXIT_FAILURE;
//}
}
}
}
close_socket(sock);
return EXIT_SUCCESS;
}
Your server is sending only when the socket is ready for reading, and as the client is never sending, the server isn't either. The server send should happen when the client socket turns up in the writefds, although actually this isn't the correct way to use that feature. Really you should just send, and only add into and worry about writefds if send() caused EAGAIN/EWOULDBLOCK.
You could be getting an undetected error in the client:
if((bytes_received = recv(sock, buf, BUF_SIZE, 0)) > 1)
{
buf[bytes_received] = '\0';
fprintf(stdout, "Received %s", buf);
}
This should continue:
else if (bytes_received == 0)
{
fprintf(stdout, "peer disconnected\n");
break;
}
else // < 0: error
{
fprintf(stdout, "recv() error %s\n", strerror(errno));
break;
}
You need to print the actual error like this whenever you get an error from a system call.

Second recv call doesn't receive data, halts the execution in C

This is my client program that requests files from the server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_LINE 512
void setstring(char *str){
str[MAX_LINE-1]='\0';
}
int main(int argc, char * argv[]){
FILE *fp;
struct hostent *hp;
struct sockaddr_in sin;
char *host;
char filename[MAX_LINE],buf[MAX_LINE],reply[MAX_LINE],rec_line[MAX_LINE];
int s;
char msg[MAX_LINE];
int len,new_len,rec_file;
if (argc==2) {
host = argv[1];
}
else {
fprintf(stderr, "usage: simplex-talk host\n");
exit(1);
}
/* translate host name into peer's IP address */
hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "simplex-talk: unknown host: %s\n", host);
exit(1);
}
else
printf("Client's remote host: %s\n", argv[1]);
/* build address data structure */
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
sin.sin_port = htons(SERVER_PORT);
/* active open */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("simplex-talk: socket");
exit(1);
}
else
printf("Client created socket.\n");
int send_file_name,rec_msg;
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
perror("simplex-talk: connect");
close(s);
exit(1);
}
else{
printf("Client connected.\n");
/* main loop: get and send lines of text */
printf("Hello from server\n");
while(!(strcmp(reply,"bye")==0)){
printf("Enter the file name:\n");
scanf("%s",filename);
setstring(filename);
send_file_name=send(s,filename,strlen(filename)+1,0);
if(send_file_name<0)
fputs("Error sending filename",stdout);
rec_msg=recv(s,msg,sizeof(msg),0);
if(strcmp(msg,"File not found")==0)
printf("File not found\n");
else{
printf("%s\n",msg);
fp=fopen(filename,"w");
printf("CP1\n");
if(rec_file=recv(s,rec_line,sizeof(rec_line),0)>0){
printf("CP2");
printf("String recieved:%s\n",rec_line);
if(len=fwrite(rec_line,1,rec_file+1,fp)>0)
printf("Recieved file\n");
else
printf("Error writing to file\n");
}
else
printf("Not recieved\n");
}
printf("Enter 'bye' to terminate requesting files\n");
scanf("%s",reply);
}
}
return 0;
}
This is my server program that accepts request for files from the client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_PENDING 5
#define MAX_LINE 256
void setstring(char* str){
str[MAX_LINE-1]='\0';
}
int main(){
FILE *fp;
struct sockaddr_in sin;
char buf[MAX_LINE],msg[MAX_LINE],*rec_line;
int len;
int s, new_s,count;
char str[INET_ADDRSTRLEN];
int error_file,send_msg,read_line,send_file;
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr("0.0.0.0");
sin.sin_port = htons(SERVER_PORT);
/* setup passive open */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("simplex-talk: socket");
exit(1);
}
inet_ntop(AF_INET, &(sin.sin_addr), str, INET_ADDRSTRLEN);
printf("Server is using address %s and port %d.\n", str, SERVER_PORT);
if ((bind(s, (struct sockaddr *)&sin, sizeof(sin))) < 0) {
perror("simplex-talk: bind");
exit(1);
}
else
printf("Server bind done.\n");
listen(s, MAX_PENDING);
/* wait for connection, then receive and print text */
while(1) {
if ((new_s = accept(s, (struct sockaddr *)&sin, &len)) < 0) {
perror("simplex-talk: accept");
exit(1);
}
printf("Server Listening.\n");
printf("Greetings\n");
int rec_file_name=recv(new_s,buf,sizeof(buf),0);
if(rec_file_name>0)
printf("File requested:%s\n",buf);
fp=fopen(buf,"r");
if(fp==NULL)
{
fputs("File not found\n",stdout);
strcpy(buf,"File not found");
if(error_file=send(new_s,buf,strlen(buf)+1,0)>0)
fputs("Successfully send error message to client\n",stdout);
}
else{
bzero(buf,MAX_LINE);
printf("File found :) \n");
strcpy(buf,"OK");
if(send_msg=send(new_s,buf,strlen(buf)+1,0)>0)
fputs("File found message sent to client\n",stdout);
fseek(fp,0,SEEK_END);
int file_size=ftell(fp);
fseek(fp,0,SEEK_SET);
printf("File size:%d\n",file_size);
rec_line=(char *)malloc(sizeof(char)*(file_size));
read_line=fread(rec_line,1,file_size+1,fp);
printf("File read: %s\n",rec_line);
if(send_file=send(new_s,rec_line,strlen(rec_line)+1,0)>0)
printf("File string sent to client\n");
}
}
close(new_s);
}
The problem is that in the client, my second recv() call, where it is supposed to receive the contents of a file, shows nothing. The programs halts at that point, but the server programs displays that it has sent the file contents. The client doesn't receive it.
The basic problem is that you're not checking the return values to see how much data you actually sent and received. So when the client calls:
rec_msg=recv(s,msg,sizeof(msg),0);
it will receive up to sizeof(msg) (512) bytes, which is probably both the OK message the server is sending AND the file contents (after the NUL). Which means when it does a second recv call to get the contents, it blocks, because it already read the contents in the first call and there's no more data waiting in the receive buffer.
Your error-checking is haphazard, and consequently you're certainly missing a problem that occurs before the behavior you're observing. I recommend you follow RW Steven's idiom:
int n;
if( (n = recv(new_s, buf, sizeof(buf), 0)) < 0 ) {
err(EXIT_FAILURE, "recv %d", __LINE__);
}
Test every function call, and handle every error. For simple programs, just call err(3) on error. Do that consistently, and the program's behavior will be much less mysterious (if still occasionally surprising). And don't be afraid of the spacebar! It's easy to hit, and easier still to read.
My other bit of advice, if I may, concerns
int send_file_name,rec_msg;
Names like that are confusing. A name is almost never an integer. For I/O sizes, just use one simple name like n, len, or size. Even if you don't care for yourself, you want to care before publishing your question in an open forum. Otherwise, when people see
send_file_name=send(s,filename,strlen(filename)+1,0);
they may think send is some function other than send(2), or that the person asking the question was careless.
The main problem I see is that neither the client nor the server are handling socket I/O correctly in general. They are not handling the cases where reads and writes transfer fewer bytes then requested, you need to loop the I/O. And the client is reading too many bytes from the server anyway, which is why your second recv() is blocking. And you are relying on a disconnect to indicate the end of the file has been reached, but that does not allow the client to do adequate error checking to know if the full file was actually received or not.
Also, when sending the content of a file, the server is attempting to read the entire file into memory (bad!), not doing adequate error checking on the file I/O, and it is treating the file content as text instead of as binary (don't use strlen() on binary data!).
Try something more like this instead:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_LINE 512
int sendstring(int sock, const char *str) {
if (!str) str = "";
int len = strlen(str) + 1;
do {
int ret = send(sock, str, len, 0);
if (ret <= 0) return -1;
str += ret;
len -= ret;
}
while (len > 0);
return 0;
}
int readbuf(int sock, void *buf, int buflen) {
char *pbuf = (char*) buf;
while (buflen > 0) {
int len = recv(sock, pbuf, buflen, 0);
if (len <= 0) return -1;
pbuf += len;
buflen -= len;
}
return 0;
}
int readstring(int sock, char *str, int maxlen) {
while (maxlen > 0) {
if (recv(sock, str, 1, 0) <= 0) return -1;
if (*str == '\0') return 0;
++str;
--maxlen;
}
return -2;
}
int readfile(int sock, int fd) {
int filesize;
char buf[MAX_LINE];
if (readbuf(sock, &filesize, sizeof(filesize)) < 0) return -1;
filesize = ntohl(filesize);
while (filesize > 0) {
int len = readbuf(sock, buf, min(sizeof(buf), filesize));
if (len < 0) return -1;
if (fwrite(buf, len, 1, fp) != 1) return -2;
filesize -= len;
}
return 0;
}
int main(int argc, char * argv[]) {
char filename[MAX_LINE], reply[MAX_LINE];
if (argc != 2) {
fprintf(stderr, "usage: simplex-talk host\n");
exit(1);
}
char *host = argv[1];
/* translate host name into peer's IP address */
struct hostent *hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "simplex-talk: unknown host: %s\n", host);
exit(1);
}
if (hp->h_addrtype != AF_INET) {
fprintf(stderr, "simplex-talk: unsupported address type %d for host: %s\n", hp->h_addrtype, host);
exit(1);
}
/* build address data structure */
struct sockaddr_in sin;
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
sin.sin_port = htons(SERVER_PORT);
printf("Host's remote IP: %s\n", inet_ntoa(&sin.sin_addr));
/* active open */
int s = socket(PF_INET, SOCK_STREAM, 0);
if (s < 0) {
perror("simplex-talk: socket");
exit(1);
}
printf("Client created socket.\n");
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
perror("simplex-talk: connect");
close(s);
exit(1);
}
printf("Client connected.\n");
/* main loop: get and send lines of text */
do {
printf("Enter the file name ('bye' to quit):\n");
if (scanf("%512s", filename) != 1) {
printf("Error reading filename\n");
break;
}
if (strcmp(filename, "bye") == 0) {
sendstring(s, "bye");
break;
}
if (sendstring(s, filename) < 0) {
printf("Error sending filename\n");
break;
}
if (readstring(s, reply, sizeof(reply)) < 0) {
printf("Error reading reply\n");
break;
}
if (strcmp(reply, "OK") != 0) {
printf("%s\n", reply);
if (strcmp(reply, "bye") == 0) break;
continue;
}
FILE *fp = fopen(filename, "wb");
if (!fp) {
printf("Error opening file\n");
break;
}
printf("Receiving file\n");
int ret = readfile(s, fd);
fclose(fp);
if (ret < 0) {
if (ret == -2)
printf("Error writing file\n");
else
printf("Error reading file\n");
break;
}
printf("Received file\n");
}
while (1);
close(s);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_PENDING 5
#define MAX_LINE 512
int sendbuf(int sock, void *buf, int buflen) {
char *pbuf = (char*) buf;
while (len > 0) {
int len = send(sock, pbuf, buflen, 0);
if (len <= 0) return -1;
pbuf += len;
buflen -= len;
}
return 0;
}
int sendstring(int sock, const char *str) {
if (!str) str = "";
return sendbuf(sock, str, strlen(str) + 1);
}
int sendfile(int sock, int fd) {
char buf[MAX_LINE];
struct stat s;
if (fstat(fd, &s) < 0) return -2;
int pos = ftell(fp);
if (pos == -1) return -2;
int file_size = s.st_size - pos;
int tmp_file_size = htonl(file_size);
if (sendbuf(sock, &tmp_file_size, sizeof(tmp_file_size)) < 0) return -1;
while (file_size > 0) {
int len = fread(buf, 1, min(sizeof(buf), file_size), fp);
if (len < 1) return -2;
if (sendbuf(sock, buf, len) < 0) return -1;
file_size -= len;
}
return 0;
}
int readstring(int sock, char *str, int maxlen) {
while (maxlen > 0) {
if (recv(sock, str, 1, 0) <= 0) return -1;
if (*str == '\0') return 0;
++str;
--maxlen;
}
return -2;
}
int main() {
char msg[MAX_LINE];
struct sockaddr_in sin;
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);
/* setup passive open */
int s = socket(PF_INET, SOCK_STREAM, 0);
if (s < 0) {
perror("simplex-talk: socket");
exit(1);
}
printf("Server is using address %s and port %d.\n", inet_ntoa(&(sin.sin_addr)), SERVER_PORT);
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("simplex-talk: bind");
close(s);
exit(1);
}
printf("Server bind done.\n");
if (listen(s, MAX_PENDING) < 0) {
perror("simplex-talk: listen");
close(s);
exit(1);
}
printf("Server Listening.\n");
/* wait for connection, then receive and print text */
do {
int len = sizeof(sin);
int cli_s = accept(s, (struct sockaddr *)&sin, &len);
if (cli_s < 0) {
perror("simplex-talk: accept");
close(s);
exit(1);
}
printf("Client connected\n");
do {
if (readstring(cli_s, msg, sizeof(msg)) < 0) {
printf("Error reading request\n");
break;
}
if (strcmp(msg, "bye") == 0) break;
printf("File requested: %s\n", msg);
FILE *fp = fopen(msg, "rb");
if (!fp)
{
printf("Cannot open file\n");
if (sendstring(cli_s, "Cannot open file") < 0) {
printf("Error sending reply\n");
break;
}
continue;
}
printf("File found :) \n");
if (sendstring(cli_s, "OK") < 0) {
printf("Error sending reply\n");
fclose(fp);
break;
}
ret = sendfile(cli_s, fp);
fclose(fp);
if (ret < 0) {
printf("Error sending file\n");
break;
}
printf("File sent to client\n");
}
while (1);
close(cli_s);
}
while (1);
close(s);
return 0;
}

Server is not accepting connection from Client side to read data from a file

I want to read a file on Server from the Client application on Linux. I have mentioned below my Server and Client application.
On Client side I open a file (which is necessary to my requirements).
The Client receive the data which I have written on the file. Now, I want to send the received data from Client to the Server side and get back the echo to the Client.
I am facing trouble with the Server to accept the Client connection. I am glad to have a solution, where I made mistake exactly. I also appreciate If I get the solution for the code. Thanks in advance.
Server.C
#include<stdio.h>
#define BufferLength 100
/* Server port number */
#define SERVPORT 3389
int main(int argc, char *argv[])
{
/* Variable and structure definitions. */
int sd, sd2, rc, length = sizeof(int);
int totalcnt = 0, on = 1;
char temp;
char buffer[BufferLength];
//char data[BufferLength];
struct sockaddr_in serveraddr;
struct sockaddr_in their_addr;
fd_set read_fd;
struct timeval timeout;
timeout.tv_sec = 15;
timeout.tv_usec = 0;
/*To read xillybus*/
// FILE *fp;
// fp = fopen("/dev/xillybus_read_8", "r");
// if(fp==NULL)
// {
// printf("Error file open\n");
// exit(-1);
// }
// else{
// printf("File found %s\n", fp);
// }
/* Get a socket descriptor */
if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Server-socket() error");
exit (-1);
}
else
{
printf("Server-socket() is OK\n");
}
/* Allow socket descriptor to be reusable */
if((rc = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))) < 0)
{
perror("Server-setsockopt() error");
close(sd);
exit (-1);
}
else
{
printf("Server-setsockopt() is OK\n");
}
/* bind to an address */
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
printf("Using %s, listening at %d\n", inet_ntoa(serveraddr.sin_addr), SERVPORT);
if((rc = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
{
perror("Server-bind() error");
close(sd);
exit(-1);
}
else
{
printf("Server-bind() is OK\n");
}
/* Up to 10 clients can be queued */
if((rc = listen(sd, 10)) < 0)
{
perror("Server-listen() error");
close(sd);
exit (-1);
}
else
{
printf("Server-Ready for client connection...\n");
}
/* accept() the incoming connection request. */
int sin_size = sizeof(struct sockaddr_in);
if((sd2 = accept(sd, (struct sockaddr *)&their_addr, &sin_size)) < 0)
{
perror("Server-accept() error");
close(sd);
exit (-1);
}
else
{
printf("Server-accept() is OK\n");
}
/*client IP*/
printf("Server-new socket, sd2 is OK...\n");
printf("Got connection from the client: %s\n", inet_ntoa(their_addr.sin_addr));
/* Wait for up to 15 seconds on */
/* select() for data to be read. */
FD_ZERO(&read_fd);
FD_SET(sd2, &read_fd);
rc = select(sd2+1, &read_fd, NULL, NULL, &timeout);
if((rc == 1) && (FD_ISSET(sd2, &read_fd)))
{
/* Read data from the client. */
totalcnt = 0;
while(totalcnt < BufferLength)
{
/* read() from client */
rc = read(sd2, &buffer[totalcnt], (BufferLength - totalcnt));
if(rc < 0)
{
perror("Server-read() error");
close(sd);
close(sd2);
exit (-1);
}
else if (rc == 0)
{
printf("Client program has issued a close()\n");
close(sd);
close(sd2);
exit(-1);
}
else
{
totalcnt += rc;
printf("Server-read() is OK\n");
}
}
}
else if (rc < 0)
{
perror("Server-select() error");
close(sd);
close(sd2);
exit(-1);
}
/* rc == 0 */
else
{
printf("Server-select() timed out.\n");
close(sd);
close(sd2);
exit(-1);
}
/* Shows the data */
printf("Received data from the client: %s\n", buffer);
printf("Server-Echoing back to client...\n");
/*Write function*/
rc = write(sd2, buffer, totalcnt);
if(rc != totalcnt)
{
perror("Server-write() error");
rc = getsockopt(sd2, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
/* Print out the asynchronously */
/* received error. */
errno = temp;
perror("SO_ERROR was: ");
}
else
{
printf("Server-write() is OK\n");
}
close(sd);
close(sd2);
exit(-1);
}
/******************************************/
close(sd2);
close(sd);
exit(0);
return 0;
}
Client.c
#include<stdio.h>
#define BufferLength 100
#define SERVER "00.00.00.00"
/* Server's port number */
#define SERVPORT 3389
/* set the server name in the #define SERVER ... */
int main(int argc, char *argv[])
{
/* Variable and structure definitions. */
int sd, rc, length = sizeof(int);
struct sockaddr_in serveraddr;
char buffer[BufferLength];
char server[255];
char temp;
int totalcnt = 0;
struct hostent *hostp;
//char data[500] = "Hello ravi !!! "; // writes data to the server
/*To open directory and read the xillybus*/
FILE *fp;
char s[100];
fp = fopen("/dev/xillybus_read_8", "r");
if(!fp)
return 1;
while(fgets(s,100,fp)!=NULL){
printf("%s ", s);
}
//fclose(fp);
/******************************************/
/* get a socket descriptor */
if((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Client-socket() error");
exit(-1);
}
else
{
printf("Client-socket() OK\n");
}
/*If the server hostname is supplied*/
if(argc > 1)
{
/*Use the supplied argument*/
strcpy(server, argv[1]);
printf("Connecting to the server %s, port %d ...\n", server, SERVPORT);
}
else
{
/*Use the default server name or IP*/
strcpy(server, SERVER);
memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVPORT);
}
if((serveraddr.sin_addr.s_addr = inet_addr(server)) == (unsigned long)INADDR_NONE)
{
/* get host address */
hostp = gethostbyname(server);
if(hostp == (struct hostent *)NULL)
{
printf("HOST NOT FOUND --> ");
/* h_errno is usually defined */
/* in netdb.h */
printf("h_errno = %d\n",h_errno);
printf("---This is a client program---\n");
printf("Command usage: %s <server name or IP>\n", argv[0]);
close(sd);
exit(-1);
}
memcpy(&serveraddr.sin_addr, hostp->h_addr, sizeof(serveraddr.sin_addr));
}
/* connect() to server. */
if((rc = connect(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
{
perror("Client-connect() error");
close(sd);
exit(-1);
}
else
{
printf("Connection established...\n");
printf("Sending some string to the server %s...\n", server);
}
/* Write() some string to the server. */
//rc = write(sd, data, sizeof(data));
rc = write(sd,fp, sizeof(fp)); // here is my write function
if(rc < 0)
{
perror("Client-write() error");
rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, &length);
if(rc == 0)
{
/* Print out the asynchronously received error. */
errno = temp;
perror("SO_ERROR was");
}
close(sd);
exit(-1);
}
else
{
printf("Client-write() is OK\n");
printf("String successfully sent \n");
printf("Waiting the %s to echo back...\n", server);
}
totalcnt = 0;
/* Read data from the server. */
while(totalcnt < BufferLength)
{
rc = read(sd, &buffer[totalcnt], BufferLength-totalcnt); //&buffer[totalcnt],BufferLength-totalcnt
if(rc < 0)
{
perror("Client-read() error");
close(sd);
exit(-1);
}
else if (rc == 0)
{
printf("Server program has issued a close()\n");
close(sd);
exit(-1);
}
else
{
totalcnt += rc;
}
}
printf("Client-read() is OK\n");
printf("Echoed data from the server: %s\n", buffer); //data ->buffer
/* Close socket descriptor from client side. */
close(sd);
exit(0);
return 0;
}
In you client.c program, you try to send a FILE* to the server. What you are sending is the address of the file descriptor in client program and not the text contained in the file.
You send only 4 or 8 bytes (depending on architecture 32 or 64 bits), while server waits for at least 100 bytes before echoing anything. So both programs do exactly what you programmed - but not what you expected.
To send the content of a file, you read the file in a char array and send the char array. You can iterate over the file reading one buffer at a time and sending the buffer. But there is no magic allowing to send a whole file.

Resources