3 Replies - 412 Views - Last Post: 26 November 2012 - 06:37 PM Rate Topic: -----

#1 cheesey315  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 26
  • Joined: 10-November 12

Segmentation Fault with 3 way UDP chat program

Posted 26 November 2012 - 12:02 PM

I am working on a 3 way UDP chat program using C not c++. The Server compiles and runs but I don't know if it does what it is supposed to do since the client doesn't work yet.

The client compiles but when I run it I get this "Segmentation fault (core dumped)". I entered in what I was supposed to following the prompt that is displayed.

I will give both codes.

server.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

extern int errno;

int main(int argc, char *argv[]){
	char message;
	int i;
	int s;
	int fd;
	int len;
	struct sockaddr_in sin;
	int sinlength;
	char buf[4096];
	int buflen;
	char x;
	char strinput[50];
	struct sockaddr_in from;
	socklen_t fromlen;
	char reply[80] = "hi there";
	int pid;

	int action;

	if ((s = socket(PF_INET, SOCK_DGRAM,0)) < 0){
		perror("Socket");
		exit(1);
	}
	sin.sin_family - PF_INET;
	sin.sin_addr.s_addr = INADDR_ANY;
	sin.sin_port = 0;
	sinlength = sizeof(sin);

	if (bind(s, (struct sockaddr *) &sin, sinlength) < 0){
		perror("bind");
		exit(1);
	}
	
	if (getsockname(s, (struct sockaddr *) &sin, (socklen_t *) &sinlength) < 0){
		perror("getsockname");
		exit(1);
	}

	printf ("Socket is using port %d\n", sin.sin_port);
	printf ("The Server is now running.\n");

	while(1){
		message = recvfrom(s, buf, 4095, 0, (struct sockaddr *) &from, &fromlen);
		buf[message] = '\0';

		pid = fork();
	        
		if(pid==0){
			char * pch;
				if (pch = strstr (buf, ".quit")){
					printf("The Sever is now closing.\n");
					printf("Press Enter to finish closing the Sever\n");
					fflush(stdout);
					close(s);
					while('\n' != getchar());
					getchar ();
					exit(1);
				}
				if (pch = strstr (buf, ".send")){
					i = sendto(s, buf, strlen(buf), 0, (struct sockaddr *) &from, fromlen);
					if (i < 0){
						printf("errno was this: ", errno);
						printf("\n");
						if (errno == EINVAL){
							printf("yup\n");
							perror("sendto");
							exit(1);
						}
					}
				else {
					printf("\n(%s , %d) said : ", inet_ntoa(from.sin_addr), ntohs(from.sin_port));
					printf("%s", buf);
					printf("\n");
				}
			}
		}
	}
}



client.c
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>

extern int errno;

int main (int argc, char *argv[]){
	char hname[255];
	struct sockaddr_in sin;
	struct sockaddr_in lin;
	socklen_t sinlength;
	socklen_t linlength;
	struct hostent *ph;
	int thesock;
	int len;
	long address;
	char host[20];
	char strinput[4096];
	char strinput2[4096];
	char buf[4096];
	char x;
	struct sockaddr_in to_addr;
	struct sockaddr_in from;
	socklen_t fromlen;
	int i;
	char username[20];
	int pid;
	char message;	

	printf("Please enter the name of the program, your IP Address, and the port number that the server is using.\n");
	printf("Example: /client.c 172.24.24.2 9103\n");
	fgets(host, 20, stdin);
	
	strcpy(host, argv[1]);
	
	if ((ph = gethostbyname (host)) == NULL){
		switch (h_errno){
			case HOST_NOT_FOUND:
				fprintf(stderr, "%s: no such host %s\n", argv[0], host);
				exit(1);
			case TRY_AGAIN:
				fprintf(stderr, "%s: host %s, try again later\n", argv[0], host);
				exit(1);
			case NO_RECOVERY:
				fprintf(stderr, "%s: host %s   DNS ERROR\\n", argv[0], host);
				exit(1);
			case NO_ADDRESS:
				fprintf(stderr, "%s: No IP address for %s\n", argv[0], host);
				exit(1);
			default:
				fprintf(stderr, "Unknown error: %d\n", h_errno);
				exit(1);
			}
		}
	else {
		memcpy ((char *)   &sin.sin_addr, (char *) ph ->h_addr, ph -> h_length);
		printf("I get this as address: ", sin.sin_addr.s_addr);
		printf("\n");
		sin.sin_family = PF_INET;
	}
	
	i = gethostname(hname, len);

	sin.sin_port = atoi(argv[2]);
	
	if ((thesock = socket (PF_INET, SOCK_DGRAM, 0)) < 0) {
		perror ("socket");
		exit(1);
	}
	
	lin.sin_family = PF_INET;
	lin.sin_addr.s_addr = INADDR_ANY;
	lin.sin_port = 0;

	linlength = sizeof(lin);
	
	if (bind(thesock, (struct sockaddr *) &lin, linlength) < 0){
		perror ("bind");
		exit(1);
	}
	
	if (getsockname(thesock, (struct sockaddr *) &lin, (socklen_t *) &linlength) < 0){
		perror ("getsockname");
		exit(1);
	}

	printf("Local Socket is using port number ", lin.sin_port);
	printf("\n");
	
	printf("What is your username?\n");
	fgets(username, 20, stdin);
	
	len = sizeof(hname);
	sinlength = sizeof(struct sockaddr_in);
//	i = sendto(...);
	
	printf("You can send any text that you want. There are 2 special commands.\n");
	printf(".send <username> = send a private message to the username specified. (DO NOT INCLUDE <> IN THE COMMAND\n");
	printf(".quit = quit the program.\n");

	while(1){
		fgets(strinput, 4095, stdin);
		recvfrom(thesock, buf, 4095, 0, (struct sockaddr *) &from, &fromlen);
		buf[message]='\0';
		printf("\n(%s , %d) said : ", inet_ntoa(from.sin_addr), ntohs(from.sin_port));
		printf("%s", buf);
		printf("\n");
	
		pid = fork();
		
		if (pid==0){
			char * strinput2;
				if (strinput2 = strstr (strinput, ".quit")){
					printf("The Client is now closing.\n");
					printf("Press Enter to finish closing the Client\n");
					fflush(stdout);
					close(thesock);
					while ('\n' != getchar());
					getchar();
					exit(1);
				}
				if (strinput2 = strstr (strinput, ".send")){
					if (strinput2 = strstr (strinput, username)){
						fflush(stdout);
					}
				}
				else {
					sendto(thesock, strinput2, strlen(strinput2), 0, (struct sockaddr *) &sin, sizeof (struct sockaddr));
				}
			}
		}
	}

					



Any help will be appreciated. I'm not sure where I went wrong. I have looked online for guides but I didn't find them fully helpful for both programs, just bits and pieces.

Thanks.

Is This A Good Question/Topic? 0
  • +

Replies To: Segmentation Fault with 3 way UDP chat program

#2 vividexstance  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 687
  • View blog
  • Posts: 2,376
  • Joined: 31-December 10

Re: Segmentation Fault with 3 way UDP chat program

Posted 26 November 2012 - 01:35 PM

The seg fault is from line #41 in client.c. You attempt to copy a C-style string from argv[1] to host without first checking if the user passed ANY command-line arguments. You can check this by checking how large argc is.

*EDIT*: For the future, if compiling using gcc, add the '-g' option to compile with debugging symbols so you can run the program through gdb (debugger). By just doing this, setting a breakpoint at main() and stepping through the code, I was able to easily find where the seg fault occurred.

You also have a bunch of warnings that should not be overlooked. You should make an attempt to get rid of any warnings so that you minimize the possibilities for bugs/errors.

This post has been edited by vividexstance: 26 November 2012 - 01:38 PM

Was This Post Helpful? 1
  • +
  • -

#3 cheesey315  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 26
  • Joined: 10-November 12

Re: Segmentation Fault with 3 way UDP chat program

Posted 26 November 2012 - 06:19 PM

View Postvividexstance, on 26 November 2012 - 01:35 PM, said:

The seg fault is from line #41 in client.c. You attempt to copy a C-style string from argv[1] to host without first checking if the user passed ANY command-line arguments. You can check this by checking how large argc is.


I think I fixed that part but it still won't work. I'm following the correct format that is given, atleast I think I am. For the command line I enter in /client.c xxx.xx.xx.2 9103. xxx.xx.xx.2 is the gw0 IP address of the client machine. The server IP address is xxx.xx.xx.1, should that be entered instead? The 9103 changes everytime the server is run, the client must get the port number from the server by actually speaking to the person running the server (me). What am I not doing that I should be doing? I feel like its a pretty simple fix but I can't figure it out.

Here's the altered code.

#include <iostream>
#include <string>
using namespace std;

//data structure to hold id and data, our data-structure we want to use
struct data {
public:
		int id; //to hold a unique id for each element
		int data; //the data for each element, I used a simple int
};

class hasher {
		data dt[51]; //the table to hold hashed data structs
		int numel; //number of elements in table, to check if it's full
public:
		hasher();
		int hash(int &id);
		int rehash(int &id);
		int add(data &d);
		int remove(data &d);
		void output();
};

/*this is the function to give hashed id, it's a simple one...
It's better that we use a prime number for our length, thats why I used 11
and the bigger possible, it's better because we reduce our collisions*/
int hasher::hash(int &id) {
		return (id%51);
}
/*in case of ay collision(a hashed value which is already occupied before)
we use rehash function instead of hash*/
int hasher::rehash(int &id) {
		return ((id+1)%51);
}

hasher::hasher() {
		//create an array of data structure
		int i;
		for(i=0;i<=50;i++) {
				dt[i].id = -1; //set all ids to -1 to show they're empty
				dt[i].data = 0; //set all data values to 0, which is default
		}
		numel = 0;
}

int hasher::add(data &d) {
		if(numel < 51) {
				//table has empty places...
				int hashed = hash(d.id);
				if(hashed >= 0 && hashed <= 50 && dt[hashed].id == -1) {
						//slot is empty, assign new data
						dt[hashed].id = d.id;
						dt[hashed].data = d.data;
						return 0;
				} else {
						//we need to rehash the id
			int i=0;
			//try every place in table to find an empty place
			while(i<=50) {
							hashed = rehash(hashed);
							if(dt[hashed].id == -1) {
									dt[hashed].id = d.id;
									dt[hashed].data = d.data;
									return 0;
							} else if(i==50) {
									//we couldn't find the empty place
									return -1; //terminate function with error
							}
				i++; //update value of i
			}
				}
		} else {
				//table is full
				return (-1);
		}
}

int hasher::remove(data &d) {
		int hashed = hash(d.id);
		if(dt[hashed].id == d.id) {
				//this is the right one to delete
				dt[hashed].id = -1;
				numel -= 1;
				return 0;
		} else {
				//we need a rehash to find the one
		int i=0;
		while(i<=50) {
					hashed = rehash(hashed);
					if(dt[hashed].id == d.id) {
							dt[hashed].id = -1; //set the id to -1 because it is going to be empty
							numel -= 1; //decrease 1 from number of elements
							return 0; //success
					} else if(i==50) {
							return -1; //terminate function
			}
			i++; //update the value of i
				}
		}
}

void hasher::output() {
		int i;
		for(i=0;i<51;i++) {
				cout<<i<<" ->  "<<dt[i].id<<"	 "<<dt[i].data<<endl;
		}
}

int main() {
		int id=45; //first id
		int ret;
		data d;
		d.data = 52005; //a value for all records, simply
		hasher h1;
		while(ret != -1) {
				d.id=id;
				ret = h1.add(d); //add this record to table
				id += (id/5); //update the id, I wanted to show how different ids are put in table, look at output
		}
		d.id = 271861; //set to one of the ids we added to table in above loop
		h1.remove(d); //remove that record from table
		h1.output(); //see the output, notice there is one empty record, in index number 33, that was the record with id of 271861
		return 0;
}



Quote

*EDIT*: For the future, if compiling using gcc, add the '-g' option to compile with debugging symbols so you can run the program through gdb (debugger). By just doing this, setting a breakpoint at main() and stepping through the code, I was able to easily find where the seg fault occurred.

You also have a bunch of warnings that should not be overlooked. You should make an attempt to get rid of any warnings so that you minimize the possibilities for bugs/errors.


I am new to Linux, terminal, and c programming. I am a windows person by default, but I must use Linux for this program. I have some C++ programming experience but not much and no c programming experience except for what has been written in the client and server above. So I'm not sure how to compile with debugging, I just know how to gcc.

Thank you for your help.

This post has been edited by GunnerInc: 26 November 2012 - 06:24 PM
Reason for edit:: x'd out IP `dresses

Was This Post Helpful? 0
  • +
  • -

#4 cheesey315  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 26
  • Joined: 10-November 12

Re: Segmentation Fault with 3 way UDP chat program

Posted 26 November 2012 - 06:37 PM

wow I completely screwed up that last post. I put the wrong code up. I should have checked that before posting. I'm working on a few programs at once right now. That one must have been in my clipboard.

Heres the actual altered code.

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>

extern int errno;

int main (int argc, char *argv[]){
	char hname[255];
	struct sockaddr_in sin;
	struct sockaddr_in lin;
	socklen_t sinlength;
	socklen_t linlength;
	struct hostent *ph;
	int thesock;
	int len;
	long address;
	char host[20];
	char strinput[4096];
	char strinput2[4096];
	char buf[4096];
	char x;
	struct sockaddr_in to_addr;
	struct sockaddr_in from;
	socklen_t fromlen;
	int i;
	char username[20];
	int pid;
	char message;	

	printf("Please enter the name of the program, your IP Address, and the port number that the server is using.\n");
	printf("Example: /client.c 172.24.24.2 9103\n");
	fgets(host, 20, stdin);
	
	if (argc != 3){
		printf("Format entered is not correct. Exiting program.\n");
		exit(1);
	}
	else{
		strcpy(host, argv[1]);
	}
	
	if ((ph = gethostbyname (host)) == NULL){
		switch (h_errno){
			case HOST_NOT_FOUND:
				fprintf(stderr, "%s: no such host %s\n", argv[0], host);
				exit(1);
			case TRY_AGAIN:
				fprintf(stderr, "%s: host %s, try again later\n", argv[0], host);
				exit(1);
			case NO_RECOVERY:
				fprintf(stderr, "%s: host %s   DNS ERROR\\n", argv[0], host);
				exit(1);
			case NO_ADDRESS:
				fprintf(stderr, "%s: No IP address for %s\n", argv[0], host);
				exit(1);
			default:
				fprintf(stderr, "Unknown error: %d\n", h_errno);
				exit(1);
			}
		}
	else {
		memcpy ((char *)   &sin.sin_addr, (char *) ph ->h_addr, ph -> h_length);
		printf("I get this as address: ", sin.sin_addr.s_addr);
		printf("\n");
		sin.sin_family = PF_INET;
	}
	
	i = gethostname(hname, len);

	sin.sin_port = atoi(argv[2]);
	
	if ((thesock = socket (PF_INET, SOCK_DGRAM, 0)) < 0) {
		perror ("socket");
		exit(1);
	}
	
	lin.sin_family = PF_INET;
	lin.sin_addr.s_addr = INADDR_ANY;
	lin.sin_port = 0;

	linlength = sizeof(lin);
	
	if (bind(thesock, (struct sockaddr *) &lin, linlength) < 0){
		perror ("bind");
		exit(1);
	}
	
	if (getsockname(thesock, (struct sockaddr *) &lin, (socklen_t *) &linlength) < 0){
		perror ("getsockname");
		exit(1);
	}

	printf("Local Socket is using port number ", lin.sin_port);
	printf("\n");
	
	printf("What is your username?\n");
	fgets(username, 20, stdin);
	
	len = sizeof(hname);
	sinlength = sizeof(struct sockaddr_in);
//	i = sendto(...);
	
	printf("You can send any text that you want. There are 2 special commands.\n");
	printf(".send <username> = send a private message to the username specified. (DO NOT INCLUDE <> IN THE COMMAND\n");
	printf(".quit = quit the program.\n");

	while(1){
		fgets(strinput, 4095, stdin);
		recvfrom(thesock, buf, 4095, 0, (struct sockaddr *) &from, &fromlen);
		buf[message]='\0';
		printf("\n(%s , %d) said : ", inet_ntoa(from.sin_addr), ntohs(from.sin_port));
		printf("%s", buf);
		printf("\n");
	
		pid = fork();
		
		if (pid==0){
			char * strinput2;
				if (strinput2 = strstr (strinput, ".quit")){
					printf("The Client is now closing.\n");
					printf("Press Enter to finish closing the Client\n");
					fflush(stdout);
					close(thesock);
					while ('\n' != getchar());
					getchar();
					exit(1);
				}
				if (strinput2 = strstr (strinput, ".send")){
					if (strinput2 = strstr (strinput, username)){
						fflush(stdout);
					}
				}
				else {
					sendto(thesock, strinput2, strlen(strinput2), 0, (struct sockaddr *) &sin, sizeof (struct sockaddr));
				}
			}
		}
	}

					



Was This Post Helpful? 0
  • +
  • -

Page 1 of 1