Making a socket that only exits if exit message is received - c

#include <io.h>
#include <stdio.h>
#include <winsock2.h>
#include <string.h>
#define MY_PORT 8989
#define MAXBUF 256
//function prototype
int exitmsg(const char *a, const char *b);
int main(int argc, char *argv[]){
WSADATA wsa;
SOCKET sockfd ,clientfd; //define 2 sockets
struct sockaddr_in self;
char buffer[MAXBUF];
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0){
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
/*---create streaming socket---*/
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ){
perror("Socket");
exit(errno);
}
printf("Socket created.\n");
/*---initialize address/port structure---*/
/* bzero(&self, sizeof(self));*/
self.sin_family = AF_INET;
self.sin_port = htons(MY_PORT);
self.sin_addr.s_addr = INADDR_ANY;
/*---assign a port number to the socket---*/
if ((bind(sockfd, (struct sockaddr*)&self, sizeof(self)))!=0){
perror("socket--bind");
exit(errno);
}
puts("Bind done");
/*---make it a "listening socket"---*/
if ((listen(sockfd, 20))!=0){
perror("socket--listen");
exit(errno);
}
puts("Waiting for incoming connections...");
/*---forever... ---*/
while (1){
struct sockaddr_in client_addr;
int addrlen=sizeof(client_addr), checking;
/*---accept a connection (creating a data pipe)---*/
clientfd= accept(sockfd, (struct sockaddr*)&client_addr, &addrlen);
char test[20]="exit server";
int loop=0, len=strlen(buffer);
char temp; //temporary holds character to swap
int length= recv(clientfd, buffer, MAXBUF, 0);
// handle multiple requests
do {
//from server 1
for(int i=0; i<len; i++){
if(buffer[i]>=65 && buffer[i]<=90){ // check ascii value
buffer[i]= buffer[i]+32; // if uppercase thn change
}
}
//check if client want to exit
checking= exitmsg(test, buffer);
if (checking==1){
printf("Message to exit received. \n");
}
else{
//reverse
len--; // start from 0
while (loop<len){
temp=buffer[loop];
buffer[loop]=buffer[len];
buffer[len]=temp;
loop++;
len--;
}
//outputs
//ip and host port
char *ipadd=inet_ntoa(client_addr.sin_addr);
printf("IP address: %s \nPORT: %d\n", ipadd, ntohs(client_addr.sin_port));
printf("Length of message: %d\n", length);
//send back
send(clientfd, buffer, strlen(buffer), 0);
}
length= recv(clientfd, buffer, MAXBUF, 0)>0;
}while (length>0);
/*---close connection---*/
close(clientfd);
}
/*---clean up (should never get here!)---*/
close(sockfd);
WSACleanup();
return 0;
}
int exitmsg(const char *a, const char *b){
for(; (*a!='\0' && *b!='\0'); a++, b++){
if(*a==*b){
return 1;
}
}
return 0;
}
I tried to look for several references online and came up with this, however my server doesn't work as intended. Currently sends back only reverses first 3 letters string with a letter missing and secondly the original string with two characters missing. I'm using port 8989 with a passive Telnet connection. All pointers to understand what's happening would be useful as I'm very new to this.
I'm also attempting to print the ip address, port number and length of buffer for each connection made.
I'm trying to make the server handle multiple requests from a single client, however I'm wondering whether it's even possible....

Related

server sends back unwanted characters

#include <io.h>
#include <stdio.h>
#include <winsock2.h>
#include <string.h>
#define MY_PORT 8989
#define MAXBUF 256
int main(int argc, char *argv[]){
WSADATA wsa;
SOCKET sockfd ,clientfd; //define 2 sockets
struct sockaddr_in self;
char buffer[MAXBUF];
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0){
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
/*---create streaming socket---*/
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ){
perror("Socket");
exit(errno);
}
printf("Socket created.\n");
/*---initialize address/port structure---*/
/* bzero(&self, sizeof(self));*/
self.sin_family = AF_INET;
self.sin_port = htons(MY_PORT);
self.sin_addr.s_addr = INADDR_ANY;
/*---assign a port number to the socket---*/
if ((bind(sockfd, (struct sockaddr*)&self, sizeof(self)))!=0){
perror("socket--bind");
exit(errno);
}
puts("Bind done");
/*---make it a "listening socket"---*/
if ((listen(sockfd, 20))!=0){
perror("socket--listen");
exit(errno);
}
puts("Waiting for incoming connections...");
/*---forever... ---*/
while (1){
struct sockaddr_in client_addr;
int addrlen=sizeof(client_addr);
/*---accept a connection (creating a data pipe)---*/
clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen);
//create variables
int length=recv(clientfd, buffer, MAXBUF, 0);
//output in reverse order & lowercase
for(int i=0; buffer[i]!='\0'; i++){
if(buffer[i]>=65 && buffer[i]<=90){ // check ascii value
buffer[i]= buffer[i]+32; // if uppercase thn change
}
}
int loop=0, len=strlen(buffer);
char temp; //temporary holds character to swap
len--; // remove null and start from 0
while (loop<len){
temp=buffer[loop];
buffer[loop]=buffer[len];
buffer[len]=temp;
loop++;
len--;
}
//send back
send(clientfd, buffer, sizeof(buffer), 0);
/*---close connection---*/
close(clientfd);
}
/*---clean up (should never get here!)---*/
close(sockfd);
WSACleanup();
return 0;
}
The reversing of string from client works well but it also gives out many other unwanted characters behind it and two 'PuTTy's, I'm very new to socket programming so any help is much appreciated. I can't use any string functions other than strlen. Currentlly using puTTy to open server on 8989. Telnet connection is passive.
You code assumes that buffer is NUL terminated, however there is no guaranty that the NUL character will be received by recv (which may be a partial recv and this is streaming socket).
It would make more sense to reverse the data using the return value from recv (if a positive value). This way you do not have to worry about message boundaries.
int length=recv(clientfd, buffer, MAXBUF, 0);
//output in reverse order & lowercase
for(int i=0; i < length; i++){
if(buffer[i]>=65 && buffer[i]<=90){ // check ascii value
buffer[i]= buffer[i]+32; // if uppercase thn change
}
}
You are ALWAYS sending MAXBUF (ie 256) bytes because in
send(clientfd, buffer, sizeof(buffer), 0);
sizeof(buffer) is the size of the char array declared by
#define MAXBUF 256
char buffer[MAXBUF];
Fix this by using strlen(buffer) for example, or keeping the len you got previously.

read input & save in shared memory in Socket in C

I work on the server side Socket (use Telnet client) in Linux. Client input a line with command(GET/PUT/DEL, key and an associated value (spaces to seperate in between). This key-value pair is then passed accordingly on to the function(GET/PUT/DEL), which saves the data in the shared memory (keyValueStore).
Expected client side: (> is the output from Server)
GET key1
> GET:key1:key_nonexistent
PUT key1 value1
> PUT:key1:value1
PUT key2 value2
> PUT:key2:value2
DEL key2
> DEL:key2:key_deleted
Questions:
1/ i tried to use strtok() and keyValueStore to seperate & save the tokens in a normal c file, but how should I do (or transform) it into the data transfer communication between server and client?
2/ when or where should I call the command functions (e.g. int put(char* key, char* value) )? in server.c after reading the input but before giving output?
Any advices is appreicated. Thanks for your kindness!
server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define BUFSIZE 1024 // Buffer Size
#define TRUE 1
#define PORT 5678
int main() {
int rfd; // Create-Descriptor
int cfd; // Connection-Descriptor (accept)
struct sockaddr_in client;
socklen_t client_len;
char in[BUFSIZE];
int bytes_read;
// 1. socket()
rfd = socket(AF_INET, SOCK_STREAM, 0);
if (rfd < 0 ){
fprintf(stderr, "Error\n");
exit(-1);
}
//Initialize the server address by the port and IP
struct sockaddr_in server;
memset(&server, '\0', sizeof(server));
server.sin_family = AF_INET; // Internet address family: v4 address
server.sin_addr.s_addr = INADDR_ANY; // Server IP address
server.sin_port = htons(PORT); // Server port
// 2. bind()
int brt = bind(rfd, (struct sockaddr *) &server, sizeof(server));
if (brt < 0 ){
fprintf(stderr, "Error\n");
exit(-1);
}
// 3. listen() = listen for connections
int lrt = listen(rfd, 5);
if (lrt < 0 ){
fprintf(stderr, "Error\n");
exit(-1);
}
while (1) {
// 4. accept()
cfd = accept(rfd, (struct sockaddr *) &client, &client_len);
// read() = read from a socket (Client's data)
bytes_read = read(cfd, in, BUFSIZE);
while (bytes_read > 0) {
printf("sending back the %d bytes I received...\n", bytes_read);
// write() = write data on a socket (Client's data)
write(cfd, in, bytes_read);
bytes_read = read(cfd, in, BUFSIZE);
}
close(cfd);
}
close(rfd);
}
Input.c
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#define MAX_ARRAY 100
int main() {
typedef struct Value_ {
char key[MAX_ARRAY];
char value[MAX_ARRAY];
} KeyStorage;
KeyStorage storageKey[MAX_ARRAY];
char client_input[MAX_ARRAY];
char *argv[3];
char *token;
int count = 0;
while (1) {
printf("Input: ");
gets(client_input);
//get the first token
token = strtok(client_input, " ");
int i = 0;
//walk through other tokens
while (token != NULL) {
argv[i] = token;
i++;
token = strtok(NULL, " ");
}
argv[i] = NULL; //argv ends with NULL
// arg[0] = command z.B. GET, PUT
printf("Commend: %s\n", argv[0]);
strcpy(storageKey[count].key, argv[1]);
printf("Key: %s\n", storageKey[count].key);
strcpy(storageKey[count].value, argv[2]);
printf("Value: %s\n", storageKey[count].value);
count++;
if (strcmp(argv[0], "QUIT") == 0) {
break;
}
}
return 0;
}
There are a number of errors in your code. I have fixed all to build a working example. Of course, this is not your complete application and there is even a lot of room for enhancements.
I developed and tested my code with MSVC2019 under Windows but I used a #define to isolate Windows specific code so it should compile and run correctly under Linux as well (I have not tested that).
The main problem your code had is a misunderstanding of TCP connection. It is a stream oriented connection and you must assemble "command lines" yourself, receiving one character at a time.
It is only when a line is complete that you can parse it to detect the command sent by the client. I made simple: only one command "exit" does something (close the connection). Everything else is simply ignored.
I made line assembling the easy way. That means that there is no edit possible. Backspace, delete, cursor keys and more and input as any other characters and doesn't work a a user would expect. You should take care of that.
Finally, I kept the code close to what you used. This code is single user. It accept a connection, accept commands from it and only accept a new connection once the first is closed. This is not normally the way to create a server program. To make it multiuser, you should use non-blocking socket and select() or use multi-threading.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifdef WIN32
#include <WinSock2.h>
#include <io.h>
typedef int socklen_t;
#pragma warning(disable : 4996) // No warning for deprecated function names such as read() and write()
#else
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define closesocket close
#endif
#define BUFSIZE 1024 // Buffer Size
#define TRUE 1
#define PORT 5678
int main(int argc, char *argv[])
{
#ifdef WIN32
int iResult;
WSADATA wsaData;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
#endif
int rfd; // Create-Descriptor
int cfd; // Connection-Descriptor (accept)
struct sockaddr_in client;
socklen_t client_len;
char in[BUFSIZE];
int bytes_read;
// 1. socket()
rfd = socket(AF_INET, SOCK_STREAM, 0);
if (rfd < 0) {
fprintf(stderr, "Error\n");
exit(-1);
}
// Initialize the server address by the port and IP
struct sockaddr_in server;
memset(&server, '\0', sizeof(server));
server.sin_family = AF_INET; // Internet address family: v4 address
server.sin_addr.s_addr = INADDR_ANY; // Server IP address
server.sin_port = htons(PORT); // Server port
// 2. bind()
int brt = bind(rfd, (struct sockaddr*)&server, sizeof(server));
if (brt < 0) {
fprintf(stderr, "Error\n");
exit(-1);
}
// 3. listen() = listen for connections
int lrt = listen(rfd, 5);
if (lrt < 0) {
fprintf(stderr, "Error\n");
exit(-1);
}
while (1) {
client_len = sizeof(client);
cfd = accept(rfd, (struct sockaddr*)&client, &client_len);
if (cfd < 0) {
fprintf(stderr, "accept failed with error %d\n", WSAGetLastError());
exit(-1);
}
printf("Client connected\n");
while (1) {
/*
// Send prompt to client
char* prompt = "> ";
if (send(cfd, prompt, strlen(prompt), 0) <= 0) {
fprintf(stderr, "send() failed with error %d\n", WSAGetLastError());
exit(1);
}
*/
// read a line from a socket (Client's data)
int bytes_idx = -1;
while (1) {
if (bytes_idx >= (int)sizeof(in)) {
fprintf(stderr, "input buffer overflow\n");
break;
}
// Receive on byte (character) at a time
bytes_read = recv(cfd, &in[++bytes_idx], 1, 0);
if (bytes_read <= 0) // Check error or no data read
break;
/*
printf("sending back the %d bytes I received...\n", bytes_read);
if (send(cfd, &in[bytes_idx], 1, 0) <= 0) {
fprintf(stderr, "send() failed with error %d\n", WSAGetLastError());
exit(1);
}
*/
if (in[bytes_idx] == '\n') {
// Received a complete line, including CRLF
// Remove ending CR
bytes_idx--;
if ((bytes_idx >= 0) && (in[bytes_idx] == '\r'))
in[bytes_idx] = 0;
break;
}
}
if (bytes_idx > 0) { // Check for empty line
printf("Received \"%s\"\n", in);
// Check for client command
if (stricmp(in, "exit") == 0)
break;
else {
printf("Client sent unknown command\n");
}
}
}
closesocket(cfd);
printf("Client disconnected\n");
}
closesocket(rfd);
#ifdef WIN32
WSACleanup();
#endif
}

How to interpret multiple writes from many nodes connected to one socket in C

I am trying to break a work load up to 3 different computers to speed up the computation of it in C using sockets. I am able to connect 3 nodes to one head server and give them the work and compute it. The issue is I am using one read from a data structure, read(sockfd, &result, sizeof(result)), on my head server so the input comes back all in one giant line when I need to be able to add together the inputs. Am I missing something and need to create a new sockfd for each node or is there an easier way to add together the input coming back from the compute nodes? Run the code which will open the server to listen for incoming clients. Once 3 clients connect it will send a write automatically and each will beginning solving how many primes are in the range passed to it. It will return an int of how many primes are in the range on the head server with no spaces. For example 239872209818283. When I want to get 23,987 22,098 18,283
Thanks, below is the code from the head server
write(sockfd, &result, sizeof(result));//sends the structure back to client
read(sockfd, &result, sizeof(result));
printf("%d", result.numPrime);
Below is the code from the compute node
read(sockfd, &result, sizeof(result));
printf("Start: %d, End: %d", result.min, result.max);
int primeNum = numPrime(result.min, result.max);
write(sockfd, &result, sizeof(result));
Head server code
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#define MAX 257
#define PORT 9457
#define SA struct sockaddr
//The struct to be used:
typedef struct results {
int min;
int max;
int numPrime;
} results;
int setupServerSocket(int portno);//setup a server socket
int callServer(char *host, int portno);//connect to a server
//accept connections on a server socket, return the id of the new socket
int serverSocketAccept(int serverSocket);
void writeInt(int x, int socket);//write an int over the given socket
int readInt(int socket); //read an int from the given socket
int len;
struct sockaddr_in servaddr, cli;
// Function for calculating prime number between multiple nodes
void func(int sockfd, int min, int max)
{
results result;
result.min = min;
result.max = max;
result.numPrime = 0;
write(sockfd, &result, sizeof(result));//sends the structure back to client
read(sockfd, &result, sizeof(result));
printf("%d", result.numPrime);
}
// Driver function
int main()
{
int connfd[3];
int sockfd;
// socket create and verification
sockfd = setupServerSocket(PORT);
//assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
// Binding newly created socket to given IP and verification
if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
printf("socket bind failed...\n");
exit(0);
}
else
printf("Socket successfully binded..\n");
bzero(&servaddr, sizeof(servaddr));
// Now server is ready to listen and verification
if ((listen(sockfd, 5)) != 0) {
printf("Listen failed...\n");
exit(0);
}
else
printf("Server listening..\n");
len = sizeof(cli);
// Accept the data packet from client and verification
//connfd = accept(sockfd[0], (SA*)&cli, &len);
int i = 0;
while(i < 3){
while((connfd[i] = serverSocketAccept(sockfd)) < 0){}
printf("server acccept the client %d...\n", i);
i++;
}
// Function for chatting between client and server
func(connfd[0], 1000, 334000);
func(connfd[1], 334000, 667000);
func(connfd[2], 667000, 1000000);
// After chatting close the socket
close(sockfd);
}
int serverSocketAccept(int serverSocket){
return accept(serverSocket, (SA*)&cli, &len);
}
int setupServerSocket(int portno){
int sockID;
sockID = socket(AF_INET, SOCK_STREAM, 0);
if (sockID == -1) {
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
return sockID;
}
Compute node code
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#define MAX 257
#define PORT 9457
#define SA struct sockaddr
//The struct to be used:
typedef struct results {
int min;
int max;
int numPrime;
} results;
results result;
int findPrime(int);
int numPrime(int firstInt, int secondInt);
int findPrime(int numInput);
void writeInt(int x, int socket);//write an int over the given socket
void func(int sockfd){
//write(sockfd, result.min, sizeof(test));
read(sockfd, &result, sizeof(result));
printf("Start: %d, End: %d", result.min, result.max);
int primeNum = numPrime(result.min, result.max);
writeInt(primeNum, sockfd);
//write(sockfd, &result, sizeof(result));
}
int main()
{
int sockfd, connfd;
struct sockaddr_in servaddr, cli;
// socket create and varification
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("10.35.195.47"); // thing1
servaddr.sin_port = htons(PORT);
// connect the client socket to server socket
if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0) {
printf("connection with the server failed...\n");
exit(0);
}
else
printf("connected to the server..\n");
// function for chat
func(sockfd);
// close the socket
close(sockfd);
}
void writeInt(int x, int socket){
result.numPrime = x;
write(socket, &result, sizeof(result));
}
int findPrime(int numInput){
int i = 2; //declaration of variables
int j = 1;
int isPrime = 1;
int isNotPrime = 0;
while(i < numInput && j != 0){
j = (numInput % i);
i++;
}
if(j == 1){
return isPrime;
}
else{
return isNotPrime;
}
}
int numPrime(int firstInt, int secondInt){
int count = 0;
for(int i = firstInt; i < secondInt; i++){
if(findPrime(i)){
count++;
}
}
return count;
}

How to listen to data packets using UDP in C?

I wrote up this udp receive C code to listen to data packets being streamed and it seems like the code is not entering the while loop: The output of the code is as following and then it stops there with no error although the port and ip are both defined correctly and send data works:
Initialising Winsock...Initialised.
This is the socket that was created: 128
Socket created.
connects to the socket ; it then stays here and doesnt go into the loop..
Code :
#include<stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <winsock2.h>
#include <fcntl.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "wsock32.lib")
int main(int argc , char *argv[])
{
printf("started \n");
WSADATA wsa;
SOCKET s;
struct sockaddr_in server, client_addr;
int recv_size =8192;// 2000000;
char ser[recv_size] ;
int count = 0;
int addr_len;
int bytes;
char *message , server_reply[recv_size];
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
if((s = socket(AF_INET , SOCK_DGRAM , 0 )) == INVALID_SOCKET)
{ printf("Could not create socket : %d" , WSAGetLastError());
}else{ printf("This is the socket that was created: %d \n", s); }
printf("Socket created.\n");
server.sin_addr.s_addr = inet_addr("192.168.10.103");
server.sin_family = AF_INET;
server.sin_port = htonl(25000);
addr_len = sizeof(struct sockaddr);
if (connect(s, (struct sockaddr *)&server, sizeof(server))<0)
{ puts("connect error");return 1 ;
}else {puts("connects to the socket"); }
while(1) {
// if ((recv_size = recv(s, server_reply, recv_size, 0)) == SOCKET_ERROR) {
// puts("failed at receive");
// }
puts("receiving from microzed");
bytes = recvfrom(s,ser,recv_size,0,(struct sockaddr *)&client_addr,&addr_len);
//ser[bytes] = '\0';
write(1,ser,bytes);
// printf("count: %d \n ",count = count+ 1);
// printf("data received: %d \n",ser);
}
puts("works \n");
// server_reply[recv_size] = '\0';
// printf("This is what the message reply is : %d, \n ",server_reply);
printf("finished \n");
return 0;
}
I'm going to assume that it's some kind of a 'race condition' between puts() and the recv(), since nothing else shows up, it's obvious that the recvfrom() is blocking, otherwise, you'd see the rest of the output (i.e "work \n").
a easy way to test that would be setting the mode of the socket to NON_BLOCKING.
I've tried running the code with MS Visual 2015 and it runs without issues.
Output:
started
Initialising Winsock...Initialised. This is the socket that was
created: 200 Socket created. connects to the socket receiving from
microzed

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