client - searching all services using servbyport() function - c

I need to do simple client program, when I add port number and client will be serch all services for this port. Now is problem with segmentation fault in if statement.
How to return all services? In my program it will be return just one, I think.
my code:
int main (int argc, char *argv[])
{
int sockfd, n,pol, s;
int numer;
char recvline[MAXLINE +1];
char p;
struct sockaddr_in servaddr;
struct servent *sp;
if (argc != 3)
err_sys("Aby uruchomić podaj: klient <Adres IP> <port>");
s = atoi(argv[2]);
if((sp = getservbyport(s,NULL)) == NULL)
{
printf("port (s): %d \n", s);
printf("port (sp): %d \n", sp->s_port); //segmentation fault
err_sys("problem with port");
}
if((sockfd = socket(AF_INET, SOCK_STREAM, 0))<0)
err_sys("Blad utworzenia polaczenia");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = sp->s_port;
if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr)<=0)
err_sys_kom("Blad konwersji do adresu IP dla %s", argv[1]);
printf("%s", sp->s_name);
pol = connect(sockfd, (SA*) &servaddr, sizeof(servaddr));
if (pol < 0)
{
err_sys_kom("Blad polaczenie z serwerem");
close(sockfd);
exit(-1);
}
else
str_cli(stdin, sockfd , 1);
exit(0);
}

EDIT (in response to new new problem - see comments below):
You probably need to get a list of protocols and work with those in a loop. The contents of the loop should roughly be:
Call getprotoent
If the result is NULL, exit the loop.
Else, dig out the protocol name from the returned structure.
Use that name as the second argument for getservbyport
Do what you want to with the result
EDIT (in response to new problem):
if((sp = getservbyport(s,NULL)) == NULL)
So your logic is to read sp ONLY IF sp is NULL. Obviously it will segfault.
It should be:
if((sp = getservbyport(s,NULL)) != NULL)
But then you will point out another new problem:
Why is sp NULL?
This could be because (as per the earlier version of my answer), you did an atoi on something which was not an integer. It could be because of any other reason. We can't say because we don't know what input you give.
This following part of the answer was in response to an old problem that the OP asked in the same question, and has since then chosen to edit over it:
First of all: Since you're using getservbyport, you really should read about services, if you haven't already.
Now on to the error:
getservbyport is of type:
struct servent *getservbyport(int port, const char *proto);
You are passing argv[2] which is of type char * instead of an int for port.
I believe the user inputs this as an argument in your program?
If you know that a char * points to a set of characters which look like an integer, like "1024", then you can convert it to an integer with atoi.
Do this instead, on the line with the error, when calling getservbyport, while making sure you've included stdlib.h:
getservbyport(atoi(argv[2]),NULL)
If argv[2] is NOT representable as an integer, you'll get undefined behavior, so maybe, you'll want to check this first.

Related

Segmentation Fault is given, why? (C)

I've been studying C for a about 2 weeks now and decided to try my hand at a simple port scanner. I can compile the code with no errors but whenever I try to execute it I get a segmentation fault.
#include<stdio.h>
#include<sys/socket.h>
#include<errno.h>
#include<netdb.h>
#include<string.h>
#include<stdlib.h>
int scanPort(char hostaddr[], int port) {
struct hostent *host;
int err, i, sock;
struct sockaddr_in sa;
strncpy((char*)&sa , "" , sizeof sa);
sa.sin_family = AF_INET;
if (isdigit(hostaddr[0])) {
sa.sin_addr.s_addr = inet_addr(hostaddr);
} else if ((host = gethostbyname(hostaddr)) != 0) {
strncpy((char*)&sa.sin_addr , (char*)host->h_addr , sizeof sa.sin_addr);
} else {
printf("\n[!] Failed to resolve host!\n");
exit(1);
}
sa.sin_port = htons(port);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
printf("\n[!] Failed to create socket!\n");
exit(1);
}
err = connect(sock, (struct sockaddr*)&sa , sizeof sa);
close(sock);
if (err < 0) {
return 0;
} else {
return 1;
}
}
int main(int argc, char *argv[]) {
if (argc != 4) {
printf("usage: ./portscan [TARGET] [START PORT] [STOP PORT]\n");
exit(0);
}
char host[20];
strcpy(host, argv[1]);
int beginport;
int endport;
if (isdigit(argv[2]) && isdigit(argv[3])) {
beginport = atoi(argv[2]);
endport = atoi(argv[3]);
} else {
printf("[!] Invalid port range given\n");
}
printf("[*] Beginning Scan...\n\n");
int i = beginport;
for (i; i<=endport; i++) {
if (scanPort(host, i)) {
printf("Port %d: Open\n", i);
}
}
printf("\n[*] Scan complete!");
return 0;
}
I understand that there is some improper/insecure function usage within the code, but I'm just trying to get this program functioning. This is only a test, not an actual program for use.
Here is a screenshot of compiling and executing, I don't think it'll be of much help though:
UPDATE: I passed arguments to it, still get segmentation fault:
UPDATE 2: I've added a few lines to evaluate argc
Thank you for your time.
-Defalt
The crash is happening here:
if (isdigit(argv[2]) && isdigit(argv[3])) {
The isdigit function expects an int (actually a char converted to an int), but you pass in a char *. This invokes undefined behavior, which in this case (luckily for you) manifests as a crash.
You probably want to check the first character of each string, so pass in argv[2][0] and argv[3][0] to this function.
Also, this is incorrect:
strncpy((char*)&sa.sin_addr , (char*)host->h_addr , sizeof sa.sin_addr);
The strncpy function is for copying strings, not arbitrary bytes. If there is a null byte among the bytes being copied, no others bytes after that one will be copied. Use memcpy instead, which copies an exact number of bytes:
memcpy((char*)&sa.sin_addr , (char*)host->h_addr , sizeof sa.sin_addr);

C program-server function error

I am trying to learn C and I can't get these apps working. I am creating 2 apps client/server, where the client connects to a server via specified port, and sends a file name (text) to the server. The server then takes the file name, runs it through a word count function and then responds to the client with filename/line/word/character count. I have gotten the client and the server to connect and communicate but my problem is that I can't seem to pass the client input to the wordcount function properly. Also, I'm not sure my function will return properly as I haven't found an appropriate method of returning a crafted string. Any help would be appreciated. Thanks!
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
void error(const char *msg){
perror(msg);
exit(1);
}
char * wordcount(char *cfile){
int i = 0;
int ccount = 0;
int wcount = 0;
int lcount = 0;
char *fn = malloc(strlen(cfile+7));
sprintf(fn, "/Files/%s", cfile);
FILE *cfilename = fopen (fn, "r");
while ((i = fgetc(cfilename)) != EOF){
if (i == '\n') {
lcount++;
}
if (i == '\t' || i == ' '){
wcount++;
}
ccount++;
}
printf("%c contains %d words, %d characters and %d lines.\n", cfile, wcount, ccount, lcount);
return 0;
}
int main(int argc, char *argv[]){
int sock, newSock, portno, n;
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen;
char buffer[256];
int index = 5;
int lowPortNum = 2500 + (10 * index);
int highPortNum = 2500 + (10 * index) + 9;
/* Check for proper amount of args */
if (argc < 2){
fprintf(stderr, "ERROR: No port specified. Exiting...\n");
printf("NOTE: Port must be between %d & %d.\n",lowPortNum,highPortNum);
exit(1);
}
/* Create socket by using args to form components */
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock < 0){
error("ERROR: Could not create socket");
}
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if(bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
error("ERROR: Binding failed.");
return 1;
}
/* Start listening on socket */
listen(sock, 5);
puts("Server is waiting for connection...");
clilen = sizeof(cli_addr);
/* Accept connection from incoming client */
newSock = accept(sock, (struct sockaddr *) &cli_addr, &clilen);
if (newSock < 0){
error("ERROR: Accept failed.");
}
/* Read message from the client */
bzero(buffer, 256);
if (read(newSock, buffer, 255) < 0){
error("ERROR: Cannot read from socket.");
}
//debug
printf("client msg read: %s\n",buffer);
/* Send message to the client */
//wordcount(buffer);
if (write(newSock , wordcount(buffer) , 100) < 0){
error("ERROR: Cannot write to socket.");
}
close(newSock);
close(sock);
return 0;
}
Firstly, I think you've made a mistake here:
char *fn = malloc(strlen(cfile+7));
sprintf(fn, "/Files/%s", cfile);
You probably meant this:
char fn[strlen(cfile) + 8];
sprintf(fn, "/Files/%s", cfile);
You might notice that I've rearranged it a little; I think you wanted to add 7 to the return value of strlen, not to the argument of strlen. I've written 8 instead, because the extra 1 is for a '\0' which goes at the end of your string; that's extremely important. When you're crafting strings, always remember to make space for the '\0'.
Additionally, I've changed your malloc to a variable-length array. You really don't need to use dynamic storage duration (e.g. malloc) for this; try to prefer automatic storage duration unless you absolutely need dynamic storage duration.
Especially considering that your code leaks memory (which is the precise reason to avoid it unless you absolutely need it). Perhaps valgrind would be a useful tool in your development environment? Always remember to free any memory you have mallocd.
There's another error here:
FILE *cfilename = fopen (fn, "r");
while ((i = fgetc(cfilename)) != EOF){
Supposing fopen returns NULL (probably to indicate that the file doesn't exist), the calls to fgetc following it are clearly going to fail in disastrous ways. I think you meant something like this:
FILE *cfilename = fopen (fn, "r");
if (cfilename == NULL) {
/* XXX: HANDLE THIS ERROR! We'll get to this later... */
}
while ((i = fgetc(cfilename)) != EOF){
... and similarly, you've forgotten to fclose that file that was fopend. Always remember to fclose files that you have fopend.
... my problem is that I can't seem to pass the client input to the wordcount function properly
Providing the mistakes mentioned earlier are fixed, you should be able to safely pass the message received from your socket to wordcount as you have in your comment, without crashes or resource leaks: wordcount(buffer);...
You can try that if you like, but bear with me for a moment longer because you have other requirements to assess.
I'm not sure my function will return properly as I haven't found an appropriate method of returning a crafted string.
Think about how standard library functions handle this. You've used one of them here: sprintf(fn, "/Files/%s", cfile);. By accepting the destination (fn) for the string as an argument, sprintf allows you to use whichever storage duration you like. Additionally, this allows sprintf to return some other int value (which you can look up in the sprintf manual in your own time)...
If you design your function to write to a destination pointed to by an argument, like sprintf (and others) do, you'll be able to use your function however you like (e.g. automatic or dynamic storage duration?), too. You'll be able to return an int value indicating success or failure (e.g. when the fopen call fails), too.
Consider the following function, which doesn't even need a return value because there are no error modes:
typedef unsigned long long ullong;
void fcount(FILE *f, ullong *char_count, ullong *word_count, ullong *line_count)
{
rewind(f);
*char_count = 0;
*word_count = 0;
*line_count = 0;
for (;;) {
int c = fgetc(f);
switch (c) {
case EOF: return;
case '\n': (*line_count)++;
case '\t':
case ' ': (*word_count)++;
default: (*char_count)++;
}
}
}
Now consider this wrapper of that function, which does require a return value
int count(char *destination, char *filename) {
char fn[strlen(filename) + 8];
sprintf(fn, "/files/%s", filename);
FILE *f = fopen(fn, "r");
if (f == NULL) {
/* Note: This exit code is defined within <stdlib.h> */
return EXIT_FAILURE;
}
ullong char_count, word_count, line_count;
count(f, &char_count, &word_count, &line_count);
fclose(f);
sprintf(destination, "%s contains %llu words, %llu characters and %llu lines.\n", filename, word_count, char_count, line_count);
return EXIT_SUCCESS;
}
Now you can tell if your function fails or succeeds, just like many of the standard library functions! Yay!
char buf[128];
count(buf, file_name);
printf("%s", buf);
You can also access the string you intended to write... Is this all flowing together?

C code to get the interface name for the IP address in Linux

How can I get the interface name for the IP address in linux from C code ?
e.g. I'd like to get the interface name ( like etho , eth1 , l0 ) assigned for the IP address 192.168.0.1
Using /proc/net/arp you can match it. Here is a command line tool example.
usage: getdevicebyip 192.168.0.1
#include <stdio.h>
#include <fcntl.h>
int main(int argc, char **argv){
if (argc < 2) return 1;
FILE *fp = fopen("/proc/net/arp", "r");
char ip[99], hw[99], flags[99], mac[99], mask[99], dev[99], dummy[99];
fgets(dummy, 99, fp); //header line
while (fscanf(fp, "%s %s %s %s %s %s\n", ip, hw, flags, mac, mask, dev) != EOF)
if (!strcmp(argv[1],ip))
printf("%s\n",dev);
return 0;
}
You can use getifaddrs. See man 3 getifaddrs for usage information. This will only work on a Unix-like systems.
netlink is a way to do this on Linux. I think it might even be a proper way to do it on Linux (even though it isn't portable).
The strategy is:
Get a list of addresses on interfaces from the kernel by sending a netlink message.
Find the address you want (I have hard coded the one I want as address_dq) and record its interface (a number at this stage)
Get a list of interfaces by sending another netlink message,
Find the number of the interface matching the number you recorded in step (2).
Get the name of the interface.
The code below is not pretty, but I'm sure you could do a better job of it. I have been a especially sloppy by not checking for a multipart message (checking for the NLM_F_MULTI flag and for a message type of NLMSG_DONE is the way to do it). Instead I have just assumed the response to the first message is multipart -- it is on my machine -- and chewed up the NLMSG_DONE message which follows.
Code...
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/socket.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, void ** argv) {
// This is the address we want the interface name for,
// expressed in dotted-quad format
char * address_dq = "127.0.0.1";
// Convert it to decimal format
unsigned int address;
inet_pton(AF_INET, address_dq, &address);
char buf[16384];
// Our first message will be a header followed by an address payload
struct {
struct nlmsghdr nlhdr;
struct ifaddrmsg addrmsg;
} msg;
// Our second message will be a header followed by a link payload
struct {
struct nlmsghdr nlhdr;
struct ifinfomsg infomsg;
} msg2;
struct nlmsghdr *retmsg;
// Set up the netlink socket
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
// Fill in the message
// NLM_F_REQUEST means we are asking the kernel for data
// NLM_F_ROOT means provide all the addresses
// RTM_GETADDR means we want address information
// AF_INET means limit the response to ipv4 addresses
memset(&msg, 0, sizeof(msg));
msg.nlhdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
msg.nlhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
msg.nlhdr.nlmsg_type = RTM_GETADDR;
msg.addrmsg.ifa_family = AF_INET;
// As above, but RTM_GETLINK means we want link information
memset(&msg2, 0, sizeof(msg2));
msg2.nlhdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
msg2.nlhdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
msg2.nlhdr.nlmsg_type = RTM_GETLINK;
msg2.infomsg.ifi_family = AF_UNSPEC;
// Send the first netlink message
send(sock, &msg, msg.nlhdr.nlmsg_len, 0);
int len;
// Get the netlink reply
len = recv(sock, buf, sizeof(buf), 0);
retmsg = (struct nlmsghdr *)buf;
// Loop through the reply messages (one for each address)
// Each message has a ifaddrmsg structure in it, which
// contains the prefix length as a member. The ifaddrmsg
// structure is followed by one or more rtattr structures,
// some of which (should) contain raw addresses.
while NLMSG_OK(retmsg, len) {
struct ifaddrmsg *retaddr;
retaddr = (struct ifaddrmsg *)NLMSG_DATA(retmsg);
int iface_idx = retaddr->ifa_index;
struct rtattr *retrta;
retrta = (struct rtattr *)IFA_RTA(retaddr);
int attlen;
attlen = IFA_PAYLOAD(retmsg);
char pradd[128];
// Loop through the routing information to look for the
// raw address.
while RTA_OK(retrta, attlen) {
if (retrta->rta_type == IFA_ADDRESS) {
// Found one -- is it the one we want?
unsigned int * tmp = RTA_DATA(retrta);
if (address == *tmp) {
// Yes!
inet_ntop(AF_INET, RTA_DATA(retrta), pradd, sizeof(pradd));
printf("Address %s ", pradd);
// Now we need to get the interface information
// First eat up the "DONE" message waiting for us
len = recv(sock, buf, sizeof(buf), 0);
// Send the second netlink message and get the reply
send(sock, &msg2, msg2.nlhdr.nlmsg_len, 0);
len = recv(sock, buf, sizeof(buf), 0);
retmsg = (struct nlmsghdr *)buf;
while NLMSG_OK(retmsg, len) {
struct ifinfomsg *retinfo;
retinfo = NLMSG_DATA(retmsg);
if (retinfo->ifi_index == iface_idx) {
retrta = IFLA_RTA(retinfo);
attlen = IFLA_PAYLOAD(retmsg);
char prname[128];
// Loop through the routing information
// to look for the interface name.
while RTA_OK(retrta, attlen) {
if (retrta->rta_type == IFLA_IFNAME) {
strcpy(prname, RTA_DATA(retrta));
printf("on %s\n", prname);
exit(EXIT_SUCCESS);
}
retrta = RTA_NEXT(retrta, attlen);
}
}
retmsg = NLMSG_NEXT(retmsg, len);
}
}
}
retrta = RTA_NEXT(retrta, attlen);
}
retmsg = NLMSG_NEXT(retmsg, len);
}
}
When run as above, returns Address 127.0.0.1 on lo.
Using "192.168.1.x" instead of "127.0.0.1" it instead returns Address 192.168.1.x on eth0.

Store a clients struct and use it afterwards

I store my clients like this..
int MAXCLIENTS = 4;
int ClientCount = 0;
int FreeSpot[MAXCLIENTS];
typedef struct CLIENTS_FD{
int sock;
struct sockaddr_in cli_adr;
}cliuse;
cliuse MYCLIENTS[4];
do{
NewSFD = accept(ServerFD,(struct sockaddr *) &cli_addr, &clilen);
if (NewSFD < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" accept() failed");
DCSERVER = TRUE;
}
break;
}
if(ClientCount < MAXCLIENTS){
for(loop = 0; loop < MAXCLIENTS; loop++){
if(FreeSpot[loop]<0){
Clients[loop].sock = NewSFD;
break;
}
}
ClientCount++;
}
else
{
printf("Maximum Client Reached.\n");
char *sendtoclient = "Server full";
send(NewSFD, sendtoclient, strlen(sendtoclient),0);
close(NewSFD);
break;
}
ip = ntohl(cli_addr.sin_addr.s_addr);
printf(" Connection from %d.%d.%d.%d\n",
(int)(ip>>24)&0xff,
(int)(ip>>16)&0xff,
(int)(ip>>8)&0xff,
(int)(ip>>0)&0xff);
dlogs(ip);
}while(NewSFD != -1);
I know i can store my clients file descriptor but how can i store my clients struct and use it afterwards i want to send message to it?.. say i want to send message to client with ip 192.168.5.10.
thanks.
I think you miss some important point about network programming. Maybe you should read this for more details and infos how to start.
Nevertheless accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) will fill client addres structure which is second parameter (struct sockaddr *addr). You can then easily add this address to your CLIENTS_FD structure.
Clients[loop].sock = NewSFD;
Clients[loop].cli_adr = cli_addr;
assuming that Clients is cliuse (or struct CLIENTS_FD).
Anyway, like mentioned in some comments above you don't need to store this address anywhere. All you need to communicate with your client is its sockfd (which is returned by accept).
What is more there could be some bugs in your code:
int FreeSpot[MAXCLIENTS];
is uninitialized so when you try to check it
if(FreeSpot[loop]<0)
this could lead to wrong behaviour. You could simply write int FreeSpot[MAXCLIENTS] = {0}; You should then somewhere (probably inside if(FreeSpot[loop]<0) statement) add something like this FreeSpot[loop] = 1; to set it properly before next checks.
int MAXCLIENTS = 4;
int FreeSpot[MAXCLIENTS];
Since C99 it is possible to declare tables using something else than constant. This is called VLA (variable length array). Nevertheless in your case I can see no point to use VLA. Try #define MAXCLIENTS 4 instead (as suggested in some comment above).
To write to the clients, after returning from your do-while loop you can simply use something like below:
send(Clients[i].sock, msg, len, flags);
where i is number of your client (range 0-3), again assuming that Clients is cliuse (or struct CLIENTS_FD).

Why i am not able to read multiple strings in the server file?

While working in client-server programming, I have passed 3 strings in client, which will be received by server and it should be printed in there 3 times. (i.e I have used a 'for' loop which will do the read & write operations in client & server side respectively.), but in server only the 1st string is getting printed.
Please explain,
Here is my code
server.c
#include "head.h"
void readstr(int connfd ,char [][20]);
//void writestr(char * ,int);
int main(int c ,char *v[])
{
int sd,connfd,retbind;
struct sockaddr_in serveraddress ,cliaddr;
socklen_t len;
char buf[100] ,databuf[1024][4];
sd =socket( AF_INET ,SOCK_STREAM ,0);
if (sd<0)
{
exit(1);
}
memset(&serveraddress ,0 ,sizeof(serveraddress));
serveraddress.sin_family =AF_INET;
serveraddress.sin_port =htons(MYPORT);
serveraddress.sin_addr.s_addr =htonl(INADDR_ANY);
retbind =bind(sd ,(struct sockaddr*)&serveraddress ,sizeof(serveraddress
));
if(-1 ==retbind)
{
perror("bind fails ");
exit(0);
}
listen(sd ,4);
for(;;)
{
printf("i am waiting for client\n");
len =sizeof(cliaddr);
connfd = accept(sd ,(struct sockaddr*)&cliaddr ,&len);
if(connfd <0)
{
if(errno ==EINTR)
printf("interrupt");
continue;
}
printf("connection from %s\n",inet_ntop(AF_INET ,&cliaddr.sin_addr,buf ,
sizeof(buf)));
readstr(connfd ,databuf);
close(connfd);
printf("\n fini one clieni");
}
return 0;
}
void readstr(int connfd ,char str[3] [20])
{
int pointer=0 ,i=0, n,pos=0;
memset(str ,'\0',sizeof(str));
printf("\n->Connfd : %d\n",connfd);
printf("\n----->String recieved : %s\n",str);
for(i=0;i<3;i++)
{
while((n=read(connfd ,str[i] ,20)) >>0)
{
printf("Looping while\n");
pos =pos +n;
}
str[i][pos] ='\0';
}
for(i=0;i<3;i++)
{
printf("\n%s",str[i]);
}
}
client.c
#include "head.h"
void send1(int ,char*);
int main(int c,char*v[])
{
int sd,i;
int len;
char buf[20][4];
struct sockaddr_in serveraddress;
sd = socket(AF_INET ,SOCK_STREAM ,0);
if (sd<0)
perror("socket");
memset(&serveraddress ,0 ,sizeof(serveraddress));
serveraddress.sin_family =AF_INET;
serveraddress.sin_port =htons(atoi(v[1]));
serveraddress.sin_addr.s_addr =inet_addr(v[2]);
if(connect(sd,(struct sockaddr*)&serveraddress ,sizeof(serveraddress)) <
0)
{
printf("cannot connect to server");
exit(1);
}
for(i=0;i<3;i++)
{
memset(buf ,'\0',sizeof(buf));
printf("\n string");
fgets(buf[i],20,stdin);
len =strlen(buf[i]);
if(buf[i][len] =='\n')
buf[i][len]='\0';
// scanf("%s",buf[i]);
send1(sd ,(char *)buf);
}
shutdown(sd ,SHUT_WR);
}
void send1(int sd ,char *str)
{
int n ,byteswritten =0, wr;
char buf[1024];
strcpy(buf ,str);
n =strlen(buf);
while(byteswritten < n)
{
printf("\nStart writing in client side\n");
wr = write(sd , buf+byteswritten ,(n-byteswritten));
byteswritten+=wr;
}
printf("\n string sent %s" ,buf);
}
In client.c main:
char buf[20][4];
change to:
char buf[4][20];
In server.c readstr:
while((n=read(connfd ,str[i] ,20)) >>0)
change to:
while((n = read(connfd, &str[i][pos], 20)) > 0)
pos needs to be reset to 0 inside the for loop.
Also, the client reads 3 strings of up to 20 chars each from stdin and writes them to the socket.
The server expects 3 strings of exactly 20 chars each.
You should either use some kind of record separator, like \n, in your network protocol, or use fixed length, i.e. pad the input strings to 20 characters.
There may be more errors in your code, I stopped looking after finding these.
It has been over 1 hour on SO and you haven't got an answer.. to what seems like a very simple problem(odd feat). you know why?
because its very painful to go through your code.
document it!
divide it into modules - init_net(), form_pkt(),
send_pkt(), exit(),.. etc
describe your problem properly.
how many client are you running?
what happens after only first strings get printed. does you code stops, loops forever what?
have you looked through a packet capture tool like tcpdump, wireshark, etc
and before I get to the main problem.. I see things like "databuf[1024][4]" being passed to a function readstr() with formal arguments "char str[3] [20]".
couple of advice
run your code through a static tool analyzer to look for basic warnings.
strings are not a great idea to send on network, learn how to define a packet structure with header and data part, etc
also I believe you are looking for a Packet like communication instead of stream based. understand the difference!
I do not know the answer to that question unless you present it properly. this time and every next time.

Resources