i am just starting to learn how to code socket but having problem i can't solve.
so i was trying to create a telnet client and i have succeeded to receive the first message from the server but after this receive line, my program kind of stuck and won't do anything else. not even a simple printf line.
thanks in advance,
Ricky
here's the code:
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
void error_msg(char msg[256]){
printf("error at %s\n", msg);
}
void main(){
struct sockaddr_in serv_addr;
char buffer[2048], server_reply[2048];
printf("trying to connect to []...\n");
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd<0) error_msg("socket");
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("192.168.0.1");
serv_addr.sin_port = htons(23);
int conn = connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr));
if(conn<0) error_msg("connect");
printf("connected to server\n");
bzero(server_reply, 2048);
bzero(buffer, 2048);
while(1){
int n_recv = recv(sockfd , server_reply , sizeof(server_reply) , 0);
if(n_recv > 0){
printf("%s", server_reply);
sleep(1);
scanf("%s" , buffer);
int n_send = send(sockfd , buffer , sizeof(buffer), 0);
if(n_send < 0) printf("send error, server is not responding...\n");
}
if(n_recv < 0) printf("recv error, server is not responding...\n");
}
close(sockfd);
}
Without knowing exactly what the return value is, it seems likely the remote side has closed the connection:
http://linux.die.net/man/2/recv
The return value will be 0 when the peer has performed an orderly shutdown.
Look at my comment on your question and post that data and I should be able to help more.
Related
I am trying to create a simple socket connection of a client and a server.
I wrote something very basic, following this guide.
I am using the client.c:
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define PORT 8080
int client()
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char buffer[1024] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
send(sock , hello , strlen(hello) , 0 );
printf("Hello message sent\n");
valread = read( sock , buffer, 1024);
printf("%s\n",buffer );
return 0;
}
and the server.c:
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#define PORT 8080
int server()
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
char *hello = "Hello from server";
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address,
sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
valread = read( new_socket , buffer, 1024);
printf("%s\n",buffer );
send(new_socket , hello , strlen(hello) , 0 );
printf("Hello message sent\n");
return 0;
}
One important change that I want to make is running the client and the server from a single code file, where I use pthread to run the server on a single thread while running the client on another thread.
I was working with pthreads before, however this time it doesn't work properly. No message is being sent and it looks like the server is not listening. Here is what the main function looks like:
int main(){
pthread_t threads[NUM_THREADS];
int ret;
printf("In main: creating thread server\n");
ret = pthread_create(&threads[0], NULL, &server, NULL);
if (ret){
printf("ERROR; return code from pthread_create() is %d\n", ret);
exit(-1);
}
printf("In main: creating thread client\n");
ret = pthread_create(&threads[1], NULL, &client, NULL);
if (ret){
printf("ERROR; return code from pthread_create() is %d\n", ret);
exit(-1);
}
}
Where the client and server functions are basic function, exactly the same one from the guide mentioned before.
The threads are created and the main function executes without errors, but the server and client functions do not run properly. I started suspecting maybe socket connection cannot run in a thread-like configuration. Would appreciate any help in that matter.
edit:
After checking the server file execution, I noticed it get lost inside the accept function. To be more specific, in the server.c file:
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
It doesn't go past this function, meaning that it does hit the 'accept' function, and it goes inside of it, but it never leaves it. It never assign any value to new_socket nor does it go inside the if statement to hit the perror("accept");
Thank you
From the info you gave in the comments, linked with #Andreas Wenzel, #encs and #IS comments:
You need to wait for the threads to finish. add a join function to block the main thread meanwhile the other threads are running
use fflush() after every printf() to avoid issues related to buffering
The server should be in Listen state before any client tries to connect. To ensure that, setup the server in the main thread, and create a pthread for everything below the accept() function.
I have such a task, I need to write the “client” code so that the message from the “client” is sent to the server (which was created by my teacher, ip “127.0.0.1”). After the message arrives at the server (for example, “Nursultan Nazarbayev”, the server will reply “ok” and the client should send “quit”)
I'm just learning C. How to make a break with the server? I wanted to send "quit", but this did not work, there was a constant error, how can I do this?
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
char message[2048];//=(char*)malloc(sizeof(char));// transmission message
char buf[sizeof(message)];
int port,ch;
//----------------------------------------------------------------------------
if(argc!=3){
printf("Wrong number of arguments!\nThere must be 2 arguments (Port, server ip-address)!\n");
exit(0);
}
int sock; // socket descriptor
struct sockaddr_in addr; // structure with address
struct hostent* hostinfo;
port = atoi(argv[1]);
hostinfo = argv[2];
sock = socket(AF_INET, SOCK_STREAM, 0); // create TCP socket
if(sock < 0)
{
perror("socket");
exit(1);
}
// Specify server parameters
addr.sin_family = AF_INET; // Internet domains
addr.sin_port = htons(port); // or any other port ...
addr.sin_addr.s_addr=inet_addr("hostinfo");
// addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
//addr.sin_addr.s_addr = inet_addr(host_ip);
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) // establishing a connection to the server
{
perror("Connection");
exit(2);
}
while(1){//WHILE <---
//----------------------------------------------------------------------------
printf("Enter a message to the server (To exit: quit): ");
if (!strcmp(gets(message), "quit")){close(sock);return 0;}
//----------------------------------------------------------------------------
printf("sending a message to the server...\n");
send(sock, message, sizeof(message), 0); // sending a message to the server
int bytes_read = 0;
printf("Message Waiting\n");
bytes_read = recv(sock, buf, sizeof(message), 0);
printf("received %d bytes\tMessage: %s\n", bytes_read, buf); // receiving a message from the server
}//END_WHILE
return 0;
}
This probably is wrong:
addr.sin_addr.s_addr=inet_addr("hostinfo");
You are passing the literal string, "hostinfo" to the inet_addr() function. Meanwhile, you have a variable named hostinfo, to which you assign a string value, but you never use it anywhere in the program.
Maybe you meant to do this instead:
addr.sin_addr.s_addr=inet_addr(hostinfo);
P.S., I like long, descriptive names. If that was my program, the name of the variable would be something like, server_address_as_string.
I run a socket programming code for communication of multiple clients with one server. Everything happens properly but when I ctrl C to exit one of client, the server does not show as I expected. Below is the code:
Client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 4444
int main(){
int clientSocket, ret;
struct sockaddr_in serverAddr;
char buffer[1024];
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if(clientSocket < 0){
printf("[-]Error in connection.\n");
exit(1);
}
printf("[+]Client Socket is created.\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("[-]Error in connection.\n");
exit(1);
}
printf("[+]Connected to Server.\n");
while(1){
printf("Client: \t");
scanf("%s", &buffer[0]);
send(clientSocket, buffer, strlen(buffer), 0);
if(strcmp(buffer, ":exit") == 0){
close(clientSocket);
printf("[-]Disconnected from server.\n");
exit(1);
}
if(recv(clientSocket, buffer, 1024, 0) < 0){
printf("[-]Error in receiving data.\n");
}else{
printf("Server: \t%s\n", buffer);
}
}
return 0;
}
Server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 4444
int main(){
int sockfd, ret;
struct sockaddr_in serverAddr;
int newSocket;
struct sockaddr_in newAddr;
socklen_t addr_size;
char buffer[1024];
pid_t childpid;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
printf("[-]Error in connection.\n");
exit(1);
}
printf("[+]Server Socket is created.\n");
memset(&serverAddr, '\0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if(ret < 0){
printf("[-]Error in binding.\n");
exit(1);
}
printf("[+]Bind to port %d\n", 4444);
if(listen(sockfd, 10) == 0){
printf("[+]Listening....\n");
}else{
printf("[-]Error in binding.\n");
}
while(1){
newSocket = accept(sockfd, (struct sockaddr*)&newAddr, &addr_size);
if(newSocket < 0){
exit(1);
}
printf("Connection accepted from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
if((childpid = fork()) == 0){
close(sockfd);
while(1){
recv(newSocket, buffer, 1024, 0);
if(strcmp(buffer, ":exit") == 0){
printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
break;
}else{
printf("Client: %s\n", buffer);
send(newSocket, buffer, strlen(buffer), 0);
bzero(buffer, sizeof(buffer));
}
}
}
}
close(newSocket);
return 0;
}
When I press ctrl C to exit the client. On the server side, it shows:
Client:
Client:
Client:
Client:
and it's seem to loop "Client:" forever instead of showing message of printf"Disconnected from..." and continue to work with other clients as I expected. I look at this code from on youtube, they can run it properly in the video but I do not know why when I download this code and run on my computer, it gets that problem. Can anyone help me to fix that problem so that the server can print the message "Disconnection...". Thank you.
When I press ctrl C to exit the client. On the server side, it shows:
Client:
Client:
Client:
Client:
and it's seem to loop "Client:" forever instead of showing message of
printf"Disconnected from..." and continue to work with other clients
as I expected.
Your code prints the disconnection message and exits the loop only if it receives an ":exit" message from the client. If you kill the client with a Ctrl-C, then it terminates without sending any such message.
Robust server code would check the return value of the recv() call, which would return -1 to signal an error. Your server ignores that and just tries to read again, and again, and again. Although you cannot rely on getting an error in every scenario where the client goes away, the fact that your server keeps printing "Client:" indicates that you are getting one in this case.
I look at this code from on youtube, they can run it properly in the
video but I do not know why when I download this code and run on my
computer, it gets that problem.
Either what they demonstrated in the video was different from the code you've presented (maybe the video was deceptive about that), or they exited the client by typing an ":exit" command, not just killing the client.
It sounds like your client isn't properly closing the connection. If you're using Ctrl C to stop the client, then you are killing the client program and not breaking the loop. If you want to stop the client that way, you should handle SIGINT and close the socket connection.
I have a socket app written in c and I am executing on linux, but when I execute the server (./server), I get the following error:
connection failed, connection refused.
Here is the code:
server.c
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#define DEFAULT_PORT 8080
void error(char* message){
perror(message);
exit(EXIT_FAILURE);
}
void handler_client(void){
}
int main(int argc , char **argv[]){
int server_fd;
int new_socket;
int valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
char *hello = "Hello, I'm server";
if((server_fd = socket(AF_INET, SOCK_STREAM , 0)) == 0){
error("socket failed");
}
if(setsockopt(server_fd , SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT , &opt , sizeof(opt))){
error("setsockertopt");
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(DEFAULT_PORT);
if(bind(server_fd , (struct sockaddr *)&address, sizeof(address) ) < 0){
error("bind failure");
}
if(listen(server_fd , 3) < 0){
error("listen");
}
if((new_socket = accept(server_fd , (struct sockaddr *)&address , (socklen_t *)&addrlen)) < 0){
error("accept");
}
valread = read( new_socket , buffer , 1024);
printf(" message from client : %s \n",buffer);
send(new_socket , hello , strlen(hello) , 0);
printf("Hello message sent \n");
return 0;
}
client.c
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#define DEFAULT_PORT 8080
#define BUFFER_SIZE 1024
void error(char* message){
perror(message);
exit(EXIT_FAILURE);
}
int main(int argc , char** argv){
struct sockaddr_in address;
int sock = 0;
int valread;
struct sockaddr_in serv_addr;
char message[BUFFER_SIZE] = {0};
char buffer[BUFFER_SIZE] = {0};
if((sock = socket(AF_INET , SOCK_STREAM , 0)) < 0){
error("Sockert Creation fails");
}
memset(&serv_addr , '0' , sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(DEFAULT_PORT);
if(inet_pton(AF_INET , "127.0.0.1" , &serv_addr.sin_addr) <= 0){
error("Invalid address / Address not supported");
}
if(connect(sock , (struct sockaddr *)&serv_addr , sizeof(serv_addr) ) < 0){
error("connection failed");
}
printf("enter your message : ");
fgets(message , BUFFER_SIZE-1 , stdin);
send(sock , message , strlen(message) , 0);
printf("Hello message sent\n");
valread = read(sock , buffer , BUFFER_SIZE);
printf("response from buffer : %s\n",buffer);
return 0;
}
A "connection refused" error means you are trying to connection to a server IP:port that is either:
not open for listening
has too many pending client connections in its backlog
blocked by a firewall/router/antivirus.
There is no way on the client side to differentiate which condition is causing the error. All it can do is try again later, and give up after awhile.
Since your client is trying to connection to 127.0.0.1, the client and server MUST be run on the same machine. You will not be able to connect across machine boundaries, and that includes VM boundaries between host/client systems.
That being said, I see a number of mistakes in your code, but none that are causing the connection error.
Server side:
socket() returns -1 on error, not 0.
//if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0){
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
you can't set multiple socket options at a time with setsockopt(), you must set them individually with separate calls to setsockopt().
//setsockopt(server_fd , SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
setsockopt(server_fd , SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
setsockopt(server_fd , SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
Client side:
you are filling serv_addr with '0' characters instead of 0 bytes.
//memset(&serv_addr , '0' , sizeof(serv_addr));
memset(&serv_addr, 0, sizeof(serv_addr));
On both sides, you are not doing any error handling on send(). But more importantly, you are not including the message's null terminator in the send, so the peer has no way of knowing when the end of the message is reached. TCP is a streaming transport, so you need to frame your messages in your data protocol. Send the message's length before sending the message itself. Or send a unique terminator after the message. The peer can then read the length before reading the message, or read until the terminator is reached.
Both send() and read() return how many bytes were actually sent/received, which can be (and frequently is) fewer bytes than requested. You need to call them in a loop to make sure that you send/receive everything you are expecting.
Also, read() does not return a null-terminated string, but your use of printf() expects one. Check valread for error, and only if read() was successful then pass valread to printf() as an input parameter so it knows how much data is actually in the buffer:
printf("message from client : %.*s\n", valread, buffer);
printf("response from buffer : %.*s\n", valread, buffer);
I am a newbie to c socket programming and c itself. I have written a small piece of code that reads raw input from another internet socket and post the data to a webserver. the received data is always numeric. however the problem seems that the http post request happens only once instead of running in a loop and the program terminates.
following is the code example
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
//define server parameters
#define WEBIP "172.16.100.2"
int main()
{
//declare variables
struct sockaddr_in my_addr,client_addr,server_addr;
struct hostent *server_host;
int true=1;
int client_socket_id,server_socket_id;
int client_id;int sin_size;
int client_bytes_received;
char send_data [1024],recv_data[1024],post_data[1024];
server_host=gethostbyname(WEBIP2);
//create a socket to listen to client
if ((client_socket_id = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Error Creating Socket");
exit(1);
}
if (setsockopt(client_socket_id,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1) {
perror("Setsockopt");
exit(1);
}
//create socket to connect to webserver
if ((server_socket_id = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Error Creating Webserver Socket");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(7070);
my_addr.sin_addr.s_addr = INADDR_ANY;
//bzero(&(my_addr.sin_zero),8);
bzero(&(server_addr.sin_zero),8);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(WEBPORT);
server_addr.sin_addr = *((struct in_addr *)server_host->h_addr);
//bind to a socket
if (bind(client_socket_id, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))== -1) {
perror("Unable to bind");
exit(1);
}
//listen to socket
if (listen(client_socket_id, 5) == -1) {
perror("Error Listening to Socket");
exit(1);
}
printf("\n\r Waiting for client on port 7070");
fflush(stdout);
while(1)
{
sin_size = sizeof(struct sockaddr_in);
client_id = accept(client_socket_id, (struct sockaddr *)&client_addr,&sin_size);
printf("\n I got a connection from (%s , %d)",
inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
//connect to remote server
if (connect(server_socket_id, (struct sockaddr *)&server_addr,sizeof(struct sockaddr)) == -1)
{
perror("Error Connecting to Web Server");
exit(1);
}
while(1){
//send some data to client
send(client_id,"Hello, World!",13, 0);
//receive some data from client
client_bytes_received=recv(client_id,recv_data,1024,0);
recv_data[client_bytes_received] = '\0';
//print received_data
int c_length=strlen(recv_data)+11;
printf("\n\rRecieved data (%d bytes %d words)= %s " , client_bytes_received,c_length,recv_data);
//post dta to webserver
fflush(stdout);
bzero(&post_data,1024);
sprintf(post_data,"POST /environment.php HTTP/1.1\r\n"
"Host: 172.16.100.2\r\n"
"User-Agent: C Example Client\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"Content-Length: %d\r\n\r\n"
"track_data=%s",c_length,recv_data);
write(server_socket_id,post_data,strlen(post_data)+1);
bzero(&recv_data,1024);
while((client_bytes_received=read(server_socket_id,recv_data,1024))>0){
recv_data[client_bytes_received] = '\0';
if (fputs(recv_data,stdout)==EOF)
perror("web server read_error");
}
//print received_data
printf("\n\rRecieved data from webserver (%d)= %s " , client_bytes_received,recv_data);
//
bzero(&recv_data,1024);
fflush(stdout);
}
}
close(client_id);
close(client_socket_id);
return 0;
}
I have not done socket programming for years, so please bear with me. Do you need to connect, process, and then disconnect? That's the first thing that came to mind reading your code.
I am surprised this program works. You have created blocking sockets, unless you are working on a non-POSIX compliant OS. The accept call should have never returned. If accept is returning it means that your server socket is not able to go into the wait mode. Hence whatever you are seeing is most likely because of an error.
SO_NONBLOCK is the socket option you can use for creating non blocking sockets.
Since you are using the same routine for both client and server you should use select in the socket loop.