bzero in socket programming - c

I am writing a simple client/server chat program in c. I am not understanding why one program works and the other doesn't. The programs given for client and server which are working are below. When I replace bzero(&(server.sin_zero),8) with bzero((char*)server,sizeof(server)) in both codes, it throws an error that "transport endpoint is not connected". They have implemneted using the second method and it works at this site.
Client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
struct sockaddr_in server;
int s1;
char message[500];
server.sin_port = htons(5000);
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
bzero(&(server.sin_zero),8);
s1 = socket(AF_INET,SOCK_STREAM,0);
if(s1 == -1) {
perror("socket not created\n");
exit(1);
}
if(connect(s1,(struct sockaddr *)&server,sizeof(server)) == -1) {
perror("not able to connect\n");
exit(1);
}
int n = read(s1,message,500);
if(n < 0) {
perror("message not recieved\n");
exit(1);
}
printf("%s\n",message);
close(s1);
return 0;
}
Here is the program for the server.
Server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
struct sockaddr_in server,client;
int s1,s2,len;
char message[500];
server.sin_port = htons(5000);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
bzero(&(server.sin_zero),8);
s1 = socket(AF_INET,SOCK_STREAM,0);
if(s1 == -1) {
perror("socket not created\n");
exit(1);
}
if(bind(s1,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) {
perror("socket not binded\n");
exit(1);
}
if(listen(s1,5) == -1) {
perror("unable to listen");
exit(1);
}
len = sizeof(struct sockaddr_in);
s2 = accept(s1,(struct sockaddr *)&client,&len);
printf("connected");
if(s2 == -1) {
perror("unable to accept connection");
exit(1);
}
strcpy(message,"you are connected");
message[strlen(message)] = '\0';
int n = write(s2,message,strlen(message));
if(n < 0) {
perror("message not sent\n");
exit(1);
}
close(s1);
close(s2);
return 0;
}

bzero(&(server.sin_zero),8)
only zeroes out the sin_zero array.
bzero((char*)server,sizeof(server))
on the other hand, zeroes out the whole struct, thus resetting the values you set before (like sin_port).
Finally, first zero out the struct, then initialize it (just like they did it on the site you referred to; pay attention to the details :-)).

Related

C socket : connect error - invalid argument

I made a simple Process-based parallel socket program.
My client code reaches the connect part and throws an Invalid argument error, and my server doesn't ouput anything. just cursor...
I split the terminal in two to run the code.
I run the code with:
gcc -o p-server p-server.c -Wall
./p-server
gcc -o p-client p-client.c -Wall
The output is
[C] Connecting...
[C] Can't connect to a Server: Invalid argument
p-server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
//#include <sys/wait.h>
#define BUFFSIZE 4096
#define SERVERPORT 7799
int main(void){
int i, j, s_sock, c_sock;
struct sockaddr_in server_addr, client_addr;
socklen_t c_addr_size;
char buf[BUFFSIZE] = {0};
char hello[] = "Hello~ I am Server!\n";
//int option = 1;
//setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVERPORT);
server_addr.sin_addr.s_addr = inet_addr("10.0.0.131");
s_sock = socket(AF_INET, SOCK_STREAM, 0);
if (bind(s_sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1) {
perror("[S] Can't bind a socket");
exit(1);
}
if(listen(s_sock, 5)) {
perror("[S] Can't listen");
exit(1);
}
c_addr_size = sizeof(client_addr);
for ( i=0; i<3; i++) {
if ((c_sock = accept(s_sock, (struct sockaddr *) &client_addr, sizeof(client_addr))) == -1 ){
perror("[S] Can't accept a connection");
exit(1);
}
printf("[S] Connected: client IP addr=%s port=%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
//fork
switch(fork()){
case 0:
close(s_sock);
//1. say hello to client
if(send(c_sock, hello, sizeof(hello)+1, 0) == -1) {
perror("[S] Can't send message");
exit(1);
}
printf("[S] I said Hello to Client!\n");
//2. recv msg from client
if(recv(c_sock, buf, BUFFSIZE, 0) == -1) {
perror("[S] Can't receive message");
exit(1);
}
printf("[S] Client says: %s\n", buf);
exit(0);
}
close(c_sock);
}
/*
for(j=0; j<3; j++){
wait(&status);
printf("Patren waits %d\n"), wstatus;
}*/
}
p-client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUFFSIZE 4096
#define SERVERPORT 7799
int main(void){
int c_sock;
struct sockaddr_in server_addr;
socklen_t c_addr_size;
char buf[BUFFSIZE] = {0};
char hello[] = "Hi~I am Client!\n";
if((c_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVERPORT);
server_addr.sin_addr.s_addr = inet_addr("10.0.0.131");
printf("[C] Connecting...\n");
if (connect(c_sock, (struct sockaddr *) &server_addr, sizeof(server_addr) == -1)) {
perror("[C] Can't connect to a Server");
exit(1);
}
printf("[C] connected!\n");
//1. recv msg from server (maybe it's "hello")
if (recv(c_sock, buf, BUFFSIZE, 0) == -1) {
perror("[C] Can't receive message");
exit(1);
}
printf("[C] Server says: %s\n", buf);
//2. say hi to server
if(send(c_sock, hello, sizeof(hello)+1, 0) == -1) {
perror("[C] Can't send message");
exit(1);
}
printf("[C] I said Hi to Server!!\n");
printf("[C] I am going to sleep...\n");
sleep(10);
close(c_sock);
return 0;
}

How to write to the client twice?

I'm trying to send to the client the bits he has to read, then he has to read them. But for some reason he doesn't read the message, he only reads the bites,msgLength.I get the message form the server[server]The message was sent succefully.And the client is able to read only the msgLength, the msg is empty.
client:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
#include <fcntl.h>
extern int errno;
int port;
int main(int argc, char *argv[])
{
int sd;
struct sockaddr_in server;
char msg[200];
int fd;
char msgLength[200];
if (argc != 3)
{
printf("Sintax: %s <adress_server> <port>\n", argv[0]);
return -1;
}
port = atoi(argv[2]);
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Error on socket().\n");
return errno;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(argv[1]);
server.sin_port = htons(port);
if (connect(sd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1)
{
perror("[client]Erorr on connect().\n");
return errno;
}
if (recv(sd, msgLength, 2,0) < 0)
{
perror("[client]Erorr on recv() from the server.\n");
return errno;
}
bzero(msg,100);
if (recv(sd, msg, 22,0)<0){
perror("[client]Erorr on the second recv() from the server.\n");
return errno;
}
printf("msgLength: %s\n",msgLength);
printf("[client]The message recived is: %s\n", msg);
close(sd);
}
server:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/wait.h>
#define PORT 2024
extern int errno;
int main()
{
struct sockaddr_in server; r
struct sockaddr_in from;
char msg[100];
char msgrasp[100] = " ";
int sd;
pid_t pid;
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("[server]Erorr on the socket().\n");
return errno;
}
bzero(&server, sizeof(server));
bzero(&from, sizeof(from));
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(PORT);
int optval = 1;
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
*/
if (bind(sd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1)
{
perror("[server]Erorr on the bind().\n");
return errno;
}
if (listen(sd, 5) == -1)
{
perror("[server]Erorr on listen().\n");
return errno;
}
while (1)
{
int client;
int length = sizeof(from);
printf("[server]We wait on the port %d...\n", PORT);
fflush(stdout);
client = accept(sd, (struct sockaddr *)&from, &length);
if (client < 0)
{
perror("[server]Erorr on accept().\n");
continue;
}
switch (pid = fork())
{
case -1:
perror("fork");
exit(1);
break;
case 0:
close(sd);
bzero(msg, 100);
printf("[server]Sending the text...\n");
fflush(stdout);
int fd1 = open("ToSend.txt", O_RDONLY);
char msgLength[100];
read(fd1, msgrasp, 100);
sprintf(msgLength,"%ld",strlen(msgrasp)+1);
printf("msgLength: %d\n",atoi(msgLength));
if ((send(client,msgLength,sizeof(msgLength),0) && send(client, msgrasp, atoi(msgLength),0)) <= 0)
{
perror("[server]Erorr on send() to the client.\n");
continue;
}
else
printf("[server]The message was sent succefully.\n");
exit(2);
default:
wait(NULL);
close(client);
break;
}
}
}
I solved it. The problem was that the server was sending sizeof(msgLength) witch is 100, and the client was reading just 2. If i replace sizeof(msgLength) with strlen(msgLength)+1 it works just fine. Thank you all for your time.

Using printf with threads and socket programming

I was making a server using socket programming that echoes what the client says to him. But when I print out the message(send by client) and it's length, the message and it's length don't match. I am using printf to print.
What I basically want is to close the connection when the client types "exit". But strcmp("exit",clientmessage) is not working.
server code:
//for running type ./a.out anyportnumber
#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 <pthread.h>
void *function(void *s)
{
int s1;
int n;
char rmsg[500];
s1 = *(int *)s;
while((n = read(s1,rmsg,499)) > 0) {
rmsg[n] = '\0';
printf("%s %d\n",rmsg,strlen(rmsg));
bzero(rmsg,499);
}
pthread_exit(NULL);
}
int main(int arrc,char *argv[])
{
struct sockaddr_in server,client;
int s1,len;
int s2;
int n;
int i = 0;
int port;
pthread_t t1;
char message[500];
port = atoi(argv[1]);
bzero((char *)&server,sizeof(server));
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
s1 = socket(AF_INET,SOCK_STREAM,0);
if(s1 == -1) {
perror("socket not created\n");
exit(1);
}
if(bind(s1,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) {
perror("socket not binded\n");
exit(1);
}
if(listen(s1,5) == -1) {
perror("unable to listen");
exit(1);
}
len = sizeof(struct sockaddr_in);
s2 = accept(s1,(struct sockaddr *)&client,&len);
pthread_create(&t1,NULL,function,(void *)&s2);
pthread_join(t1,NULL);
close(s2);
close(s1);
return 0;
}
client side input:
shivam#shivam-HP-Pavilion-15-Notebook-PC:~$ telnet localhost 8009
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hhh
jhiklmnop
Server side output:
shivam#shivam-HP-Pavilion-15-Notebook-PC:~/Study/chat$ ./a.out 8009
hhh
5
jhiklmnop
11
Edited code:
//for running type ./a.out anyportnumber
#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 <pthread.h>
void *function(void *s)
{
int s1;
int n;
char rmsg[500];
s1 = *(int *)s;
char d[] = {'e','x','i','t','\0'};
while((n = read(s1,rmsg,499)) > 0) {
rmsg[n-2] = '\0';
if(strcmp(d,rmsg) == 0) {
write(s1,"bye",3);
close(s1);
}
rmsg[n-2] = '\n';
rmsg[n-1] = '\0';
write(s1,rmsg,strlen(rmsg));
bzero(rmsg,499);
}
pthread_exit(NULL);
}
int main(int arrc,char *argv[])
{
struct sockaddr_in server,client;
int s1,len;
int s2;
int n;
int i = 0;
int port;
pthread_t t1;
char message[500];
port = atoi(argv[1]);
bzero((char *)&server,sizeof(server));
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
s1 = socket(AF_INET,SOCK_STREAM,0);
if(s1 == -1) {
perror("socket not created\n");
exit(1);
}
if(bind(s1,(struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) {
perror("socket not binded\n");
exit(1);
}
if(listen(s1,5) == -1) {
perror("unable to listen");
exit(1);
}
len = sizeof(struct sockaddr_in);
s2 = accept(s1,(struct sockaddr *)&client,&len);
pthread_create(&t1,NULL,function,(void *)&s2);
pthread_join(t1,NULL);
close(s2);
close(s1);
return 0;
}
TCP is a stream-oriented protocol, there are no message boundaries. So you cannot write application logic that depends on the return value of read() as you are doing.
Workarounds for this are length-prefixed strings, or sending the NUL terminator through the socket. You can dream up other mechanisms too, but the client must, within the data stream, tell the server where the message ends; the TCP layer won't do that.
Besides the characters the user is typing in, you're also getting a carriage return (0xd) and linefeed (0xa) character when the user presses the Enter key. That's why you're getting a number 2 larger than you might expect.

segmentation fault when using gethostbyname

I am trying to create a proxy server which accepts requests from client and sends the response back to client after receiving message from the server.
But the program gives segmentation fault.
My 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>
int main(int argc,char *argv[])
{
struct sockaddr_in server,client;
struct hostent *host;
int s1,s2,s3,len;
int port;
char ip[100];
char path[100];
int p;
int n;
char buffer[500];
char site[500];
port = atoi(argv[1]);
bzero((char *)&server,sizeof(server));
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
s1 = socket(AF_INET,SOCK_STREAM,0);
if(bind(s1,(struct sockaddr *)&server,sizeof(server)) == -1) {
perror("can't bind");
exit(1);
}
if(listen(s1,10) == -1) {
perror("coudnt't listen");
exit(1);
}
len = sizeof(client);
s2 = accept(s1,(struct sockaddr *)&client,&len);
if(s2 == -1) {
perror("coudnt aceept");
exit(1);
}
memset(buffer,0,sizeof(buffer));
n = recv(s2,buffer,500,0);
if(n < 0) {
perror("not recieved");
exit(1);
}
sscanf(buffer, "http://%99[^:]:%99d/%99[^\n]", ip, &p, path);
bzero((char *)&client,sizeof(client));
client.sin_port = htons(80);
host = gethostbyname(ip);
bcopy((char *)host->h_addr,(char *)&client.sin_addr.s_addr,host->h_length);
client.sin_family = AF_INET;
s3 = socket(AF_INET,SOCK_STREAM,0);
if(connect(s3,(struct sockaddr *)&client,sizeof(client)) == -1) {
perror("can't connect\n");
exit(1);
}
sprintf(site,"GET http://%s/ HTTP/1.0\n\n",ip);
n = send(s3,site,strlen(site),0);
if(n < 0) {
perror("message not sent");
exit(1);
}
while(1) {
memset(site,0,sizeof(site));
n = recv(s3,site,500,0);
if(n < 0) {
perror("coudnot read");
exit(1);
}
site[n] = '\0';
send(s2,site,strlen(site),0);
}
close(s1);
close(s2);
return 0;
}
The mistake seems to be coming from gethostbyname(ip) because when I use gethostbyname("www.iiita.ac.in"), it works.
gethostbyname returns a null pointer in case of error and, thus, host->h_addr is a null dereference.
You need to check whether host is NULL or not before using it.
See http://man7.org/linux/man-pages/man3/gethostbyname.3.html

Simple socket programming code working

I am trying to study and understand BSD socket programming using these simple example C++ code for TCP-IP server and client. I have read the standard APIs like socket(), bind(), listen(), accept() and read/recv() and even got code below to compile on g++/Linux.
What I want to do is see it working in real-life, I mean run the server code, and then connect to it using the client and send data from client-to-server and vice-a-versa and verify the data received. All this within two linux boxes(Ubuntu) in my same network segment. I have private IPv4 addresses given to those two Linux machines.
What should be the setup to achieve this and what code changes in the server and client code below, would be needed to achieve this over the network setup described above? I want to really see it working over network in real time?
Also any further pointers to code, blog articles to study hands-on socket programming/network programming would help.
//TCP SERVER
#include<sys/socket.h>
#include<netinet/in.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <arpa/inet.h>
//#include <fcntl.h>
#include <unistd.h>
main()
{
char buf[100];
socklen_t len;
int k,sock_desc,temp_sock_desc;
struct sockaddr_in client,server;
memset(&client,0,sizeof(client));
memset(&server,0,sizeof(server));
sock_desc = socket(AF_INET,SOCK_STREAM,0);
server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = 7777;
k = bind(sock_desc,(struct sockaddr*)&server,sizeof(server));
k = listen(sock_desc,20); len = sizeof(client);
temp_sock_desc = accept(sock_desc,(struct sockaddr*)&client,&len);
while(1)
{
k = recv(temp_sock_desc,buf,100,0);
if(strcmp(buf,"exit")==0)
break;
if(k>0)
printf("%s",buf);
} close(sock_desc);
close(temp_sock_desc);
return 0;
}
//TCP CLIENT
#include<sys/socket.h>
#include<netinet/in.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <arpa/inet.h>
//#include <fcntl.h>
#include <unistd.h>
main()
{
char buf[100];
struct sockaddr_in client;
int sock_desc,k;
sock_desc = socket(AF_INET,SOCK_STREAM,0);
memset(&client,0,sizeof(client));
client.sin_family = AF_INET;
client.sin_addr.s_addr = inet_addr("127.0.0.1");
client.sin_port = 7777;
k = connect(sock_desc,(struct sockaddr*)&client,sizeof(client));
while(1)
{
gets(buf);
k = send(sock_desc,buf,100,0);
if(strcmp(buf,"exit")==0)
break;
}
close(sock_desc);
return 0;
}
Add some error handling to your code, that will likely reveil something, eg:
Server:
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
//#include <fcntl.h>
#include <unistd.h>
main()
{
int sock_desc = socket(AF_INET, SOCK_STREAM, 0);
if (sock_desc == -1)
{
printf("cannot create socket!\n");
return 0;
}
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(7777);
if (bind(sock_desc, (struct sockaddr*)&server, sizeof(server)) != 0)
{
printf("cannot bind socket!\n");
close(sock_desc);
return 0;
}
if (listen(sock_desc, 20) != 0)
{
printf("cannot listen on socket!\n");
close(sock_desc);
return 0;
}
struct sockaddr_in client;
memset(&client, 0, sizeof(client));
socklen_t len = sizeof(client);
int temp_sock_desc = accept(sock_desc, (struct sockaddr*)&client, &len);
if (temp_sock_desc == -1)
{
printf("cannot accept client!\n");
close(sock_desc);
return 0;
}
char buf[100];
int k;
while(1)
{
k = recv(temp_sock_desc, buf, 100, 0);
if (recv == -1)
{
printf("\ncannot read from client!\n");
break;
}
if (recv == 0)
{
printf("\nclient disconnected.\n");
break;
}
if (k > 0)
printf("%*.*s", k, k, buf);
if (strcmp(buf, "exit") == 0)
break;
}
close(temp_sock_desc);
close(sock_desc);
printf("server disconnected\n");
return 0;
}
Client:
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
//#include <fcntl.h>
#include <unistd.h>
main()
{
int sock_desc = socket(AF_INET, SOCK_STREAM, 0);
if (sock_desc == -1)
{
printf("cannot create socket!\n");
return 0;
}
struct sockaddr_in client;
memset(&client, 0, sizeof(client));
client.sin_family = AF_INET;
client.sin_addr.s_addr = inet_addr("127.0.0.1");
client.sin_port = htons(7777);
if (connect(sock_desc, (struct sockaddr*)&client, sizeof(client)) != 0)
{
printf("cannot connect to server!\n");
close(sock_desc);
}
char buf[100];
char c = '\n';
char *p_buf;
int k, len;
while(1)
{
gets(buf);
len = strlen(buf);
p_buf = buf;
while (len > 0)
{
k = send(sock_desc, p_buf, len, 0);
if (k == -1)
{
printf("cannot write to server!\n");
break;
}
p_buf += k;
len -= k;
}
k = send(sock_desc, &c, 1, 0);
if (k == -1)
{
printf("cannot write to server!\n");
break;
}
if (strcmp(buf, "exit") == 0)
break;
}
close(sock_desc);
printf("client disconnected\n");
return 0;
}
On the server side you will need to change the address 127.0.0.1 to 0.0.0.0 to enable connections from anywhere. You can also use telnet instead of your client code and therefore check that the server is working as expected. Also investigate if you have the snoop command on your variety of Linux.
On the client side you need to use the IP address of the server machine
You need to make the following changes.
Port number - use htons i.e.
server - server.sin_port = htons(7777);
client - client.sin_port = htons(7777);
Server - get it to accept from any address - i.e. server.sin_addr.s_addr = INADDR_ANY;
Hope that helps somewhat
it should be like this.
if (connect(sock_desc, (struct sockaddr*)&client, sizeof(client)) != 0)

Resources