C Language: Why I cannot transfer file from server to client? - c

I want to ask, why I cannot transfer file from server to client?
When I start to send the file from server, the client side program has a problem. So, I spend some times to check the code, but I still cannot find out the problem
Can anyone point out the problem for me?
ps. Thanks for the administarator fix the code first.
ps2. I also want to know what is the error
When I execute the program, the client side program will "hang" without telling the reason.
It is difficult for me to trace the error...
thanks a lot!
client side code
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdarg.h>
#include <winsock2.h>
#include <direct.h>
#define SA struct sockaddr
#define S_PORT 5678
#define MAXLEN 1000
#define true 1
void errexit(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
WSACleanup();
exit(1);
}
int main(int argc, char *argv [])
{
WSADATA wsadata;
SOCKET sockfd;
int number,message;
char outbuff[MAXLEN],inbuff[MAXLEN];
char PWD_buffer[_MAX_PATH];
struct sockaddr_in servaddr;
FILE *fp;
int numbytes;
char buf[2048];
if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0)
errexit("WSAStartup failed\n");
if (argc != 2)
errexit("client IPaddress");
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET )
errexit("socket error: error number %d\n", WSAGetLastError());
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(S_PORT);
if ( (servaddr.sin_addr.s_addr = inet_addr(argv[1])) == INADDR_NONE)
errexit("inet_addr error: error number %d\n", WSAGetLastError());
if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) == SOCKET_ERROR)
errexit("connect error: error number %d\n", WSAGetLastError());
if ( (fp = fopen("C:\\users\\pc\\desktop\\COPY.c", "wb")) == NULL){
perror("fopen");
exit(1);
}
printf("Still NO PROBLEM!\n");
//Receive file from server
while(1){
numbytes = read(sockfd, buf, sizeof(buf));
printf("read %d bytes, ", numbytes);
if(numbytes == 0){
printf("\n");
break;
}
numbytes = fwrite(buf, sizeof(char), numbytes, fp);
printf("fwrite %d bytes\n", numbytes);
}
fclose(fp);
close(sockfd);
return 0;
}
server side code
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdarg.h>
#include <winsock2.h>
#include <direct.h>
#include <io.h>
#define SA struct sockaddr
#define S_PORT 5678
#define MAXLEN 1000
void errexit(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
WSACleanup();
exit(1);
}
int main(int argc, char *argv [])
{
WSADATA wsadata;
SOCKET listenfd, connfd;
int number, message, numbytes;
int h, i, j, alen;
int nread;
struct sockaddr_in servaddr, cliaddr;
FILE *in_file, *out_file, *fp;
char buf[4096];
if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0)
errexit("WSAStartup failed\n");
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd == INVALID_SOCKET)
errexit("cannot create socket: error number %d\n", WSAGetLastError());
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(S_PORT);
if (bind(listenfd, (SA *) &servaddr, sizeof(servaddr)) == SOCKET_ERROR)
errexit("can't bind to port %d: error number %d\n", S_PORT, WSAGetLastError());
if (listen(listenfd, 5) == SOCKET_ERROR)
errexit("can't listen on port %d: error number %d\n", S_PORT, WSAGetLastError());
alen = sizeof(SA);
connfd = accept(listenfd, (SA *) &cliaddr, &alen);
if (connfd == INVALID_SOCKET)
errexit("accept failed: error number %d\n", WSAGetLastError());
printf("accept one client from %s!\n", inet_ntoa(cliaddr.sin_addr));
fp = fopen ("client.c", "rb"); // open file stored in server
if (fp == NULL) {
printf("\nfile NOT exist");
}
//Sending file
while(!feof(fp)){
numbytes = fread(buf, sizeof(char), sizeof(buf), fp);
printf("fread %d bytes, ", numbytes);
numbytes = write(connfd, buf, numbytes);
printf("Sending %d bytes\n",numbytes);
}
fclose (fp);
closesocket(listenfd);
closesocket(connfd);
return 0;
}

Have you tried running the program under the debugger both on the client and server side to see where it hangs? I would check first if any bytes are sent and then work from there.
There are a couple of problems I noticed with the code that might or might not trigger this behaviour:
You're using write() to send data down a socket. The correct socket function would be send(), not write(). Keep in mind that send() might send fewer bytes than you asked it to so you might have to check and loop to get the whole buffer sent.
Same goes for the client, you want to use recv() and not read().
Both send() and recv() return -1 if there was any sort of problem. You need to handle this condition and preferably also check what the actual error was.
Socket programming is different from using plain files and there are a few more pitfalls due to the network generally being a little more flaky than your average file system.

You're also closing a socket using close(), not closesocket() in client.

Related

IPv6 Server in c - recvfrom failed

i have written a small c-program for an IPv6 server with winsock2.h When I run the program in Visual Studio, I get the following message all the time: recvfrom failed
I just can't find the error in the recvfrom function. Maybe someone can see why my program does not work at this point, thanks! :-)
Best regards,
Ken
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[]) {
SOCKET server_socket;
struct sockaddr_in6 server_addr, client_addr;
socklen_t client_len;
char buf[1024];
char clientIP[256];
WSADATA data;
WORD version = MAKEWORD(2, 2);
if (WSAStartup(version, &data) == SOCKET_ERROR) {
printf("WSASStartup failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
server_socket = socket(AF_INET6, SOCK_DGRAM, 0);
if (server_socket == -1) {
printf("creating socket failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("creating socket successful\n");
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_addr = in6addr_any;
server_addr.sin6_family = AF_INET6;
server_addr.sin6_port = htons(5001);
if (bind(server_socket, (const struct sockaddr*) & server_addr,
sizeof(server_addr)) == -1) {
printf("bind socket failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("bind socket successful\n");
}
while (1) {
memset(&client_addr, 0, sizeof(client_addr));
memset(buf, 0, sizeof(buf));
if (recvfrom(server_socket, (char*)buf, 1024, 0,
(struct sockaddr*) & client_addr,
sizeof(client_addr)) == -1) {
printf("recvfrom failed\n");
WSACleanup();
exit(EXIT_FAILURE);
}
else {
printf("recvfrom successful");
}
printf("%s\n", buf);
printf("IP: %s\n", inet_ntop(AF_INET6, &client_addr.sin6_addr,
clientIP, 256));
}
closesocket(server_socket);
WSACleanup();
return 0;
}
You are misusing recvfrom(). The fromlen parameter expects to receive an int* pointer that points to an int, which on input specifies the byte size of the sockaddr buffer being passed in the from parameter, and on output receives the byte size of the sockaddr written to the from buffer.
There are also some other minor bugs in your code:
WSAStartup() does not return SOCKET_ERROR on failure, it returns an actual error code.
you are ignoring the return value of recvfrom(), which tells you how many bytes were actually written to your buf. You are assuming buf is always null-terminated when passing it to printf("%s"), but that is not guaranteed. You are zeroing out buf to initialize it with null terminators, which is fine if recvfrom() receives a datagram containing less than 1024 bytes. But if it receives a datagram with exactly 1024 bytes than all of your null terminators will be overwritten and there will be no terminator left for printf() to find (if recvfrom() receives a datagram with more than 1024 bytes, it will fail with a WSAEMSGSIZE error, which is not a fatal error but you are treating it as if it were). Rather than rely on any null terminators at all, you can pass the return value of recvfrom() to printf() for the buffer size. No need to waste overhead zeroing out what recvfrom() will overwrite.
Try this instead:
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char* argv[]) {
SOCKET server_socket;
struct sockaddr_in6 server_addr, client_addr;
int client_len, num_recvd;
char buf[1024];
char clientIP[256];
WSADATA data;
WORD version = MAKEWORD(2, 2);
int errCode = WSAStartup(version, &data);
if (errCode != 0) {
printf("WSAStartup failed, error %d\n", errCode);
WSACleanup();
return EXIT_FAILURE;
}
server_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (server_socket == INVALID_SOCKET) {
errCode = WSAGetLastError();
printf("creating socket failed, error %d\n", errCode);
WSACleanup();
return EXIT_FAILURE;
}
printf("creating socket successful\n");
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_addr = in6addr_any;
server_addr.sin6_family = AF_INET6;
server_addr.sin6_port = htons(5001);
if (bind(server_socket, (struct sockaddr*) &server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
errCode = WSAGetLastError();
printf("bind socket failed, error %d\n", errCode);
closesocket(server_socket);
WSACleanup();
return EXIT_FAILURE;
}
printf("bind socket successful\n");
while (1) {
client_len = sizeof(client_addr);
num_recvd = recvfrom(server_socket, buf, sizeof(buf), 0, (struct sockaddr*) &client_addr, &client_len);
if (num_recvd == SOCKET_ERROR) {
errCode = WSAGetLastError();
if (errCode != WSAEMSGSIZE) {
printf("recvfrom failed, error %d\n", errCode);
closesocket(server_socket);
WSACleanup();
return EXIT_FAILURE;
}
printf("recvfrom truncated a datagram larger than %u bytes!\n", sizeof(buf));
num_recvd = sizeof(buf);
}
else {
printf("recvfrom successful\n");
}
printf("%.*s\n", num_recvd, buf);
printf("IP: %s\n", inet_ntop(AF_INET6, &client_addr.sin6_addr, clientIP, 256));
}
closesocket(server_socket);
WSACleanup();
return 0;
}

Address family not supported by protocol UDP C Error sending

I'm trying to implement communication by UDP protocol, and I'm getting an error: "Error sending: Address family not supported by protocol". I've checked in Google for this problem but couldn't managed to find answer.
Please be patient, I'm only starting my adventure with coding in C.
Here is a C code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#define BUFLEN 512
// define function that deals with errors
void error(const char *msg)
{
perror(msg); // print error msg
exit(1); // exit the main() function
}
int main(int argc, char *argv[])
{
struct sockaddr_in serv1_addr, serv2_addr, cli1_addr, cli2_addr; //definicja struktur adresów servera i clienta
struct hostent *server; //defines host addres struct
int cl1_sockfd, se1_sockfd, se2_sockfd, i, c1len = sizeof(cli1_addr), c2len = sizeof(cli2_addr), recv_len, portno1,portno2; // creates inits
int cli1_len = sizeof(cli1_addr);
int cli2_len = sizeof(cli2_addr);
char buf[BUFLEN];
if (argc < 4) {
fprintf(stderr,"ERROR, no port provided\n"); // deal with wrong port
exit(1);
}
//tworzenie soceketu servera
if ((se1_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
error("socket1"); //if socket() return -1 -- error
}
if ((se2_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
error("socket2"); //if socket() return -1 -- error
}
//zero out the structure
memset( &serv1_addr, 0, sizeof(serv1_addr)); //put zero into structure
memset( &serv2_addr, 0, sizeof(serv2_addr)); //put zero into structure
portno1 = atoi(argv[2]); // get port number
portno2 = atoi(argv[3]);
serv1_addr.sin_family = AF_INET; // specify address family (IPv4)
serv1_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv1_addr.sin_port = htons(portno1); // set port number
serv2_addr.sin_family = AF_INET; // specify address family (IPv4)
serv2_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv2_addr.sin_port = htons(portno2); // set port number
if(connect(se1_sockfd,(struct sockaddr *) &serv1_addr, sizeof(serv1_addr)) < 0)
error ("ERROR connecting1"); //if connection failed
if(connect(se2_sockfd,(struct sockaddr *) &serv2_addr, sizeof(serv2_addr)) < 0)
error ("ERROR connecting2"); //if connection failed
while(1) //inf loop
{
printf("Please enter the message: "); //write the msg to socket
bzero(buf, 512); //fill buffer with zeros
fgets(buf, 512, stdin); //read into buffer
if( sendto( se1_sockfd, buf, BUFLEN, 0, (struct sockaddr*) &cli1_addr, cli1_len) < 0)
error ("Error sending1");
if( sendto( se2_sockfd, buf, BUFLEN, 0, (struct sockaddr*) &cli2_addr, cli2_len) < 0)
error ("Error sending2");
if (recvfrom(se1_sockfd, buf, BUFLEN, 0, (struct sockaddr *) &cli1_addr, &cli1_len) == -1){
error("recivfrom()1"); //if reciving failed -- error
}
printf("Data: %s\n", buf);
if (recvfrom(se2_sockfd, buf, BUFLEN, 0, (struct sockaddr *) &cli2_addr, &cli2_len) == -1){
error("recivfrom()2"); //if reciving failed -- error
}
printf("Data: %s\n", buf);
}
close(se1_sockfd);
close(se2_sockfd);
return 0;
}
Thanks for your help. ;)
Your issue is likely because of uninitialized destination address. sendto() takes destination address as the one before the last argument. But you are trying to provide not-initialized address (like for recvfrom())
if( sendto( se1_sockfd, buf, BUFLEN, 0, (struct sockaddr*) &cli1_addr, cli1_len) < 0)
error ("Error sending1");
^^^
Try serv1_addr instead ?
Also need to provide appropriate size.
One more thing. As long as you use sendto() - no need to perform connect(). UDP is connectionless and connect() only establishes default destination address for those who is going to use send() on such socket. But this is not your case because you provide destination address each time you call sendto(). Even more - you may use different addresses each time.
P.S. Reference: sendto()

Unix Domain Socket Code Fails on Embedded Device

I've added a Unix domain socket to a project I'm working on. The socket has a simple function, it simply broadcasts data that the code extracts from another device, the idea is that other applications will be able to read this data from the socket.
I've written a simple server code, and when I run the code on my laptop, using a Ubuntu 10.04 VM, it works perfectly well. However, when I copy the code over onto the embedded device I'm using the code fails, when my application tries to write to the socket the code exits.
In /var/log/messages I see the following messages:
Dec 2 15:12:17 box local1.info my-app[17338]: Socket Opened
Dec 2 15:12:17 box local1.err my-app[17338]: Socket Failed
Dec 2 15:12:17 box local1.err my-app[17338]: Protocol wrong type for socket
Dec 2 15:12:38 box local1.info ./server[17178]: accept failed: Invalid argument
Here is the server code:
#include <stdio.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include<syslog.h>
#define SV_SOCK_PATH "/tmp/rtig.sock" //path to be used by socket
#define BUF_SIZE 256 //Max length of string listened to
#define BACKLOG 5
int main(int argc, char *argv[]){
struct sockaddr_un addr;
int sfd, cfd; //File Descriptors for the server and the client
ssize_t numRead; //Length of the string read from the client.
u_int8_t buf[BUF_SIZE]; //String that reads messages
char plain[BUF_SIZE]; //Plain string for writing to the log
memset(plain, 0, sizeof plain); //blank out plain string
openlog(argv[0], LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); //Write the messages to the syslog
//---Declare socket--------------------------------------
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sfd!=0){
syslog(LOG_INFO, "socket success");
}
else{
syslog(LOG_INFO, "socket unsuccessful");
}
//--Test to see if there's already a socket at SV_SOCK_PATH, and remove it if there is.
if (remove(SV_SOCK_PATH) == -1 && errno !=ENOENT){
syslog(LOG_INFO, "error removing socket");
}
//-----------------------------------------------------------
//--blank out the socket address, then write the information to it
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SV_SOCK_PATH, sizeof(addr.sun_path)-1); //ensure path is null terminated
//----Bind the socket to the address-------------------------------------
if (bind(sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un))!=0){
syslog(LOG_INFO, "bind unsuccessful");
}
else{
syslog(LOG_INFO, "bind successful");
}
//------------------------------------------------------------------------
//-----Listen on the socket-----------------------------------------------
if (listen(sfd, BACKLOG) != 0){
syslog(LOG_INFO, "listen failed");
}
else{
syslog(LOG_INFO, "listen succeeded");
}
//-------------------------------------------------------------------------
//--------Accept messages on the socket------------------------------------
socklen_t csize;
while(1){
cfd = accept(sfd, (struct sockaddr *)&addr,&csize);
if (cfd < 0) {
syslog(LOG_INFO, "accept failed: %s", strerror(errno));
}
while ( (numRead=read(cfd, buf, BUF_SIZE)) > 0 ){
dump_packet(buf, numRead);
}
}
//-------------------------------------------------------------------------
//---code never gets here but this is how to close the log and the socket--
closelog();
close(cfd);
}
And here's a simple version of the client that connects to this server from my app:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SV_SOCK_PATH "/tmp/rtig.sock" //path to be used by socket
#define BACKLOG 5
int isDaemon = 1;
void etmlog(int level, char *message)
{
isDaemon == 1 ? syslog(level, message) : printf(message);
}
int main(){
struct sockaddr_un addr;
unsigned int sockfd;
ssize_t numRead;
if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) > 0) {
etmlog(LOG_INFO, "Socket Opened\n");
}
else {
etmlog(LOG_ERR, "Socket Failed:\n");
etmlog(LOG_ERR, strerror(errno));
exit(-1);
}
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SV_SOCK_PATH, sizeof(addr.sun_path) - 1); // -1 ensures null terminated string
if (connect
(sockfd, (struct sockaddr *)&addr,
sizeof(struct sockaddr_un)) == -1) {
etmlog(LOG_ERR, "Socket Failed\n");
etmlog(LOG_ERR, strerror(errno));
exit(1);
} else {
etmlog(LOG_INFO, "Socket Connection Successful\n");
}
while (1){
// some data is read into buf up here
if (write(sockfd, buf, rdlen) < 0) {
etmlog(LOG_ERR, "Write to Socket Failed:");
etmlog(LOG_ERR, strerror(errno));
}
}
close(sockfd);
return 0;
}
I appreciate that I've just posted a lot of code to read through, but I'd be very grateful if someone could give me a few pointers on this.
You are not using accept correctly. The third argument must be initialized to the size of the second argument, so that accept won't overflow it. See man accept.

berkeley sockets, running simple client and server connecting

I'm just starting out on networking programming in c. I followed a simple tutorial to create a server which accepts a connection and prints out the message sent from the client.
the client takes an argument as the address of the server.
I'm not sure how to specify the address of the server? Is it my machine name?
I'm running the server in one terminal and trying to connect from another. Thanks for any help :)
here's the server code
`#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
#define BUFLEN 1500
int fd;
ssize_t i;
ssize_t rcount;
char buf[BUFLEN];
printf("test1");
fd = socket (AF_INET,SOCK_STREAM,0);
if (fd == -1){
printf("Oh dear, something went wrong with read()! %s\n", strerror(errno));
}
struct sockaddr_in addr;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_port = htons(500);
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
printf("cannot bind socket");
}
if (listen(fd, 20) == -1) {
printf("unable to listen");
}
int connfd;
struct sockaddr_in cliaddr;
socklen_t cliaddrlen = sizeof(cliaddr);
connfd = accept(fd, (struct sockaddr *) &cliaddr, &cliaddrlen);
if (connfd == -1) {
printf("unable to accept");
}
rcount = read(fd, buf, BUFLEN);
if (rcount == -1) {
// Error has occurred
}
for (i = 0; i < rcount; i++) {
printf("%c", buf[i]);
}
}`
printf("test1");
You should add "\n" (newline char) at the end of printed string, so that it prints immediately. Without "\n", printf() buffers its output, and you don't see them.
addr.sin_port = htons(500);
Ports 0 - 1023 are called "well known port" and reserved to the system (root). You should use port 1024 or greater for a test program like this. Changing it from 500 to 1500 (for example) binds successfully.
(You don't see the error message "cannot bind socket" because it has no "\n", as I said above.)
rcount = read(fd, buf, BUFLEN);
You should read from connfd, instead of fd. With these changes, it worked for me.
(I used "telnet localhost 1500" as a client.)

c program client server

I have written a client and server c program, which I have taken from example code.
I want to write a iterative client and server program,
i.e. after client send a string, then the server print that string and then send back a string to client
then the client print the string inputted by server, and so on until the client input 'exit' to quit.
I have modified the code that the client and server is iterative
also, if client input 'exit', the program will quit
But I have a question, I don't know how to make the client to receive the string which is inputed by server, I only can make the server to receive the client's string
Please feel free to provide hints
Many thanks!
my code
client.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdarg.h>
#include <winsock2.h>
#define SA struct sockaddr
#define S_PORT 4321
#define BufferStoreLEN 1024
void errexit(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
WSACleanup();
exit(1);
}
int main(int argc, char **argv)
{
WSADATA wsadata;
SOCKET sockfd, listenfd, connfd;
int i, n, q, len, alen, out;
char str[BufferStoreLEN+1];
char cmp[] = "exit";
char* BufferStore;
struct sockaddr_in servaddr, cliaddr;
if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0)
errexit("WSAStartup failed\n");
if (argc != 2)
errexit("wrong arg");
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET )
errexit("socket error: error number %d\n", WSAGetLastError());
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(S_PORT);
if ( (servaddr.sin_addr.s_addr = inet_addr(argv[1])) == INADDR_NONE)
errexit("inet_addr error: error number %d\n", WSAGetLastError());
if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) == SOCKET_ERROR)
errexit("connect error: error number %d\n", WSAGetLastError());
do {
printf("Input: ");
scanf("%s", str);
out = htonl(strlen(str));
BufferStore = malloc(strlen(str));
for( i=0; i<strlen(str); i++)
BufferStore[i] = str[i];
out = send(sockfd, BufferStore, strlen(str), 0);
/*
if ( strcmp( cmp, str ) != 0 )
{
printf("Server's response:\n");
n = recv(connfd, BufferStore, BufferStoreLEN, 0);
while (n > 0) {
BufferStore[n] = '\0';
printf("%s\n", BufferStore);
n = recv(connfd, BufferStore, BufferStoreLEN, 0);
}
}*/
}while(strcmp(cmp,str)!=0);
closesocket(sockfd);
WSACleanup();
free(str);
free(BufferStore);
return 0;
}
server.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdarg.h>
#include <winsock2.h>
#include <Windows.h>
#define SA struct sockaddr
#define MAXLINE 4096
#define S_PORT 4321
#define BufferStoreLEN 1024
void errexit(const char *format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
WSACleanup();
exit(1);
}
int main(int argc, char **argv)
{
WSADATA wsadata;
SOCKET listenfd, connfd;
SOCKET sockfd;
int number, out;
int i, n, q, alen;
struct sockaddr_in servaddr, cliaddr;
char BufferStore[BufferStoreLEN+1];
char* Store;
char str[BufferStoreLEN+1];
int flag = 1;
if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0)
errexit("WSAStartup failed\n");
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd == INVALID_SOCKET)
errexit("cannot create socket: error number %d\n", WSAGetLastError());
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(S_PORT);
if (bind(listenfd, (SA *) &servaddr, sizeof(servaddr)) == SOCKET_ERROR)
errexit("can't bind to port %d: error number %d\n", S_PORT, WSAGetLastError());
if (listen(listenfd, 5) == SOCKET_ERROR)
errexit("can't listen on port %d: error number %d\n", S_PORT, WSAGetLastError());
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET )
errexit("socket error: error number %d\n", WSAGetLastError());
for ( ; ; )
{
alen = sizeof(SA);
connfd = accept(listenfd, (SA *) &cliaddr, &alen);
if (connfd == INVALID_SOCKET)
errexit("accept failed: error number %d\n", WSAGetLastError());
n = recv(connfd, BufferStore, BufferStoreLEN, 0);
while (n > 0){
BufferStore[n] = '\0';
printf("%s\n", BufferStore);
printf("Input: ");
scanf("%s",str);
out = htonl(strlen(str));
Store = malloc(strlen(str));
for( q=0; q<strlen(str); q++)
Store[q] = str[q];
out = send(sockfd, Store, strlen(str), 0);
n = recv(connfd, BufferStore, BufferStoreLEN, 0);
}
closesocket(sockfd);
WSACleanup();
free(str);
free(BufferStore);
}
}
One thing that's important to understand about stream sockets (SOCK_STREAM) is that they present you with a stream of bytes (hence the name :-)), without any "packet boundaries".
Specifically, if you send() 100 bytes of data from the client, the server may recv() it as
one recv() call returning 100 bytes
two recv()s of 50 bytes each
one recv() 90 bytes followed by 10 recv()s of 1 byte
... etc ...
Your code appears to assume that what you send() on one end will be delivered in a single recv() call at the other end. For small chunks of data, that may work, but it's not something you can/should rely on.
In general, to do a command/response scenario like you're setting up, you need to have a way for the server to recognize "that's the end of the command, I should respond now". For example, if you're sending text strings, you can use a newline (\n) as the "end of command" marker.
The server would thus do multiple recv() calls (each one appending to a buffer) until it sees a \n (or an error), then send the response back; the client would do something similar when reading the response.
Your server is running inside an infinite loop, so to be able to send data that is input in the server application to the client application, you would have to read the user input in a different thread then send that to the user, as the infinite loop is currently blocking the current thread.

Resources