Im programming a server/client program and have a weird problem here....
The server binds a socket and listening to a socket. But it is stucked at accepting the client. It is a simulation of a bank program. The server stores a balance of one account and do what the client wants. The weird situation is that I've got no error messages at accepting and the server prints my message on the console "Accepted", but it did not do the next print message. But the writing of the balance to the client did well because the client gets the right value.....the next print message is also ignored by the server.....whats wrong here??? The program is not ready yet and i'm only testing a few functionalities here.
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#define MAX 20
int main(int argc, char **argv){
int sockfd,csocket;
struct sockaddr_in addr,client_addr;
socklen_t clilen;
clilen = sizeof(client_addr);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
fprintf(stderr, "Error in opening socket - %s\n", strerror(errno));
return EXIT_FAILURE;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(argv[1]));
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) < 0){
fprintf(stderr, "Error in binding - %s\n", strerror(errno));
return EXIT_FAILURE;
}
printf("Bind\n");
int list = listen(sockfd, SOMAXCONN);
if (list < 0) {
fprintf(stderr, "Error in listening - %s\n", strerror(errno));
return EXIT_FAILURE;
}
printf("Listening\n");
char sel;
int tmp,bal=666;
while(1) {
//newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
csocket = accept(sockfd,(struct sockaddr *) &client_addr,&clilen);
if (csocket < 0) {
fprintf(stderr, "Error in accepting - %s\n", strerror(errno));
return EXIT_FAILURE;
}
printf("Accepted\n");
printf("Writing balance");
if (write(csocket,&bal,sizeof(int))<0){
fprintf(stderr, "Error in Writing - %s", strerror(errno));
return EXIT_FAILURE;
}
printf("Writing balance");
if(read(csocket, &sel, sizeof(char))<0){
fprintf(stderr, "Error in reading - %s\n", strerror(errno));
return EXIT_FAILURE;
}
printf("User wählt:%c\n",sel);
/********Einzahlen**********/
if (sel=='e'){
printf("Neuer Kontostand: %d", bal);
if(read(csocket, &tmp, sizeof(int))<0){
fprintf(stderr, "Error in accepting - %s\n", strerror(errno));
return EXIT_FAILURE;
}
bal+=tmp;
printf("Neuer Kontostand: %d", bal);
}
if(sel=='q'){
close(csocket);
printf("User beendet\n");
}
}
}
The Client
{add include part here}
int main(){
int sockfd;
socklen_t addrlen;
addrlen = sizeof(struct sockaddr_in);
struct sockaddr_in addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
char ip[16];
printf("IP (Press 0 for 127.0.0.1):");
scanf("%15s", ip);
//printf("\n");
if (ip[0]=='0'){
strcpy(ip,DEFAULT_IP);
printf("Setting IP to 127.0.0.1\n");
}
printf("%s",ip);
int port;
printf("Port:");
scanf("%d",&port);
printf("\n");
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr=inet_addr(ip);
int tmp;
if (connect(sockfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in))<0){
fprintf(stderr, "Error in connecting - %s\n", strerror(errno));
}
printf("Connected\n");
int bal,w;
if(read(sockfd, &bal, sizeof(int))<0){
fprintf(stderr, "Error in accepting - %s\n", strerror(errno));
return EXIT_FAILURE;
}
printf("Balance:%d\n",bal);
printf("Geld [e]inzahlen\n"); //add money to account
printf("Geld [a]uszahlen\n"); //Getting money from account
char msg[MAX];
printf("Enter your choce:\n");
scanf("%s",msg);
if (msg[0]=='e'){
printf("How much?:\n");
scanf("%i",&w);
if (write(sockfd,&w,sizeof(int))<0 ){
fprintf(stderr, "Error in Writing - %s", strerror(errno));
return EXIT_FAILURE;
}
bal+=w;
}
printf("sended");
if (close(sockfd) < 0) {
fprintf(stderr, "Error in closing socket - %s\n", strerror(errno));
}
}
The immediate problem is combination of two things.
First, you print "Accepted" without newline. Standard output is line buffered, so it will not be printed until you print a newline (or read input from stdin, or explicit fflush(stdout);).
Second, you then enter read, which apparently never returns. Theoretically, also the write could block, but you say client receives the write, so server must be stuck at the read.
End result, your server program is indefinitely stuck at the read. And the output you thought you printed is stuck at the stdout buffers, waiting to be flushed.
The reason for this is simple: your client writes only 4 bytes, but your server tries to read 4+1 bytes. So actually it is the 2nd read at server, which blocks indefinitely.
Some general hints:
At Stack Overflow, please look at the preview and make sure your code is properly indented, or fewer people will bother to even look at it (hint: avoid TABs, use only spaces to indent, to avoid extra hassle).
Always check return value of any scanf functions, and doubly so if you are reading user input from keyboard. Even if it is just experimental code, you don't want to waste time solving bugs which are not bugs but normal behaviour of scanf.
When copy-pasting, try to fix the strings you copy paste, such as function names in your error messages, or you will be confused by "wrong" error message texts of your own.
You need a call to the select() function to test if the file descriptor is ready prior to the accept(). Also look up fd_set and the related FD_ZERO, FD_SET, and FD_ISSET macros. They are needed to monitor whether the socket is ready to accept the incoming connection. This is a great resource for socket programming.
Related
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
void error(char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3)
{
fprintf(stderr, "usage %s hostname port\n", argv[0]);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0);
{
error("ERROR opening socket");
}
server = gethostbyname(argv[1]);
if (server == NULL)
{
fprintf(stderr, "ERROR, no such host\n");
exit(0);
}
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr,server->h_length);
serv_addr.sin_port = htons(portno);
if(connect(sockfd, &serv_addr, sizeof(serv_addr)) < 0)
{
error("ERROR connecting");
}
printf("Please enter the message:");
bzero(buffer, 256);
fgets(buffer, 255, stdin);
n = write(sockfd, buffer, strlen(buffer));
if (n <0)
{
error("ERROR reading from socket");
}
printf("%s\n", buffer);
return 0;
}
When I run this program, I got the error
ERROR opening socket: Success
then the program does nothing. Also, I got the warning that
warning: passing argument 2 of ‘connect’ from incompatible pointer type [enabled by default]
if(connect(sockfd,&serv_addr, sizeof(serv_addr)) < 0)
^
In file included from Clientown.c:3:0:
/usr/include/sys/socket.h:138:12: note: expected ‘const struct sockaddr *’ but argument is of type ‘struct sockaddr_in *’
extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);
How is this happening? I am new to c and I really stuck with this code. Is there something wrong with the connect? Does the warning matter? Can someone help to me fix it? Thanks.
You have a semicolon where there should not be a semicolon:
if (sockfd < 0);
{
error("ERROR opening socket");
}
As a result, the error() function will always be called, even if the if condition fails. You want:
if (sockfd < 0)
{
error("ERROR opening socket");
}
Penguin Brian already answered the stated question, but I'd like to point out that since the asker is using POSIX/BSD sockets, they should also use the proper interfaces, namely getaddrinfo(). It handles both name and port/service translation, and supports IPv4 and IPv6 (allowing the caller to restrict to either one if desired, of course).
The man 3 getaddrinfo man page does include two example programs (client and server type), but here's mine, for illustration, with sufficient error checking:
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
int main(int argc, char *argv[])
{
struct addrinfo hints, *list, *curr;
const char *host, *port;
int sockfd, result;
if (argc != 3 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
printf("\n");
printf("Usage: %s [ -h | --help ]\n", argv[0]);
printf(" %s host port\n", argv[0]);
printf("\n");
return EXIT_FAILURE;
}
host = argv[1];
port = argv[2];
/* "" or "-" host refers to loopback. */
if (!host[0] || (host[0] == '-' && !host[1]))
host = NULL;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* TCP */
hints.ai_protocol = 0;
hints.ai_flags = AI_ADDRCONFIG;
list = NULL;
result = getaddrinfo(host, port, &hints, &list);
if (result) {
fprintf(stderr, "%s.\n", gai_strerror(result));
return EXIT_FAILURE;
}
for (curr = list; curr; curr = curr->ai_next) {
sockfd = socket(curr->ai_family, curr->ai_socktype, curr->ai_protocol);
if (sockfd == -1)
continue;
if (connect(sockfd, curr->ai_addr, curr->ai_addrlen) != -1)
break;
close(sockfd);
sockfd = -1;
}
if (sockfd == -1) {
freeaddrinfo(list);
fprintf(stderr, "Cannot connect.\n");
return EXIT_FAILURE;
}
printf("Descriptor %d is now connected. Disconnecting.\n", sockfd);
fflush(stdout);
if (close(sockfd)) {
fprintf(stderr, "Error closing socket: %s.\n", strerror(errno));
return EXIT_FAILURE;
}
printf("Done.\n");
return EXIT_SUCCESS;
}
Note that the above code does not record or report the error messages from the connect() call, because the getaddrinfo() interface provides multiple alternatives, and I'm not sure which of the errors produced in a typical case is the proper one to report. (Remember that even in a successful connection case, one or more of the connect() calls in the loop may have failed, without any actual "error" having occurred.) The getaddrinfo() call itself will fail if the host (node) or port (service) part is invalid.
In my own applications, I tend to use an error cookie -- one bit per error -- to record all the errors from the connect() calls for one result list from a getaddrinfo() call. The errors I test for are EADDRINUSE (local port already in use), ECONNREFUSED (connection refused), ENETUNREACH (network unreachable), EACCES (permission denied), EADDRNOTAVAIL (all ephemeral ports already in use), EAFNOSUPPORT (address family (IPv4/IPv6) not supported), and a catch-all for all other errors.
If none of the connect() calls succeed, I check the cookie for errors that did occur -- as an unordered set; i.e., ignoring the order in which they occurred --, and report the first match to the above list. It's not foolproof by any measure, more like trying-to-be-helpful heuristic, and I suspect that a generic error message ("Cannot connect" or similar -- this is what browsers do, after all) is generally just as useful to most users.
On the second question: You pass a pointer to a specific Internet socket address structure, but connect expects a generic socket address structure, so simply cast one type of pointer to the other:
connect(sockfd, (const struct sockaddr *)&serv_addr, sizeof(serv_addr)
This warning is actually almost irrelevant, since all pointer types on modern architectures have the same size.
I coded this little server and it doesn't work. The message directly at the beginning isn't printed out as well and I don't know how to analyse the problem by using gdb. Could you help me? Is there any library missing or whats wrong?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 7890
int main(void) {
printf("HelloWorld");
int sockfd, sock_client;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
printf("Could no open socket\n");
}
int yes = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (int)) == -1) {
printf("Coud not reuse\n");
}
printf("socket was created");
struct sockaddr_in sockaddr_host, sockaddr_client;
sockaddr_host.sin_family = AF_INET;
sockaddr_host.sin_port = htons(PORT);
sockaddr_host.sin_addr.s_addr = 0;
memset(&(sockaddr_host.sin_zero), '\0', 8);
if (bind(sockfd, (struct sockaddr *) &sockaddr_host, sizeof (sockaddr_host)) == -1) {
printf("Could not bind socket");
}
if (listen(sockfd, 1) == -1) {
printf("Could not start listening");
} else {
printf("Server is listening on %s: %d", inet_ntoa(sockaddr_host.sin_addr), ntohs(sockaddr_host.sin_port));
}
while (1) {
socklen_t client_length = sizeof (sockaddr_client);
if ((sock_client = accept(sockfd, (struct sockaddr *) &sockaddr_client, &client_length)) == -1) {
printf("Could not accept connection");
}
printf("sever: got connection from %s on port %d", inet_ntoa(sockaddr_client.sin_addr), ntohs(sockaddr_client.sin_port));
char message[] = "Hello\n";
if (send(sockfd, message, sizeof (message), 0) == -1) {
printf("Could not send message");
}
close(sock_client);
close(sockfd);
}
return 0;
}
If you were missing a library, the linker would already complain.
Standard output is usually line buffered. Add a newline after HelloWorld and you will see at least the first output.
printf("HelloWorld\n");
Same with the other printf.
After adding \n to each printf, you will see
HelloWorld
socket was created
Server is listening on 0.0.0.0: 7890
When you now connect to your server, e.g. with netcat
nc localhost 7890
your server will output
sever: got connection from 127.0.0.1 on port 36496
Some errors remain though.
if(send(sockfd, message, sizeof(message), 0) == -1) {
should be rather
if(send(sock_client, message, sizeof(message) - 1, 0) == -1) {
Otherwise the server sends the message to itself. Also sizeof(message) includes the final \0.
Finally, you shouldn't close(sockfd);, if you want to continue receiving further connection requests beyond the first one.
As you said
The message directly at the beginning isn't printed out as well
After the printf add fflush as
printf("HelloWorld");
fflush(stdout);
Is there any library missing
I don't thinks so any library is missing because you have successfully compiled the program and created the executable.
Although it seems to be correctly implemented, it keeps on returning me ERROR when I establish a connection using the loopback address(127.0.0.1).
In addition to a simple TCP Client/Server connection, I have added an additional case:
If the client tries to send data but finds the connection closed, it is closed too. I perform it by checking if received data is equal to 0 (recv).
Given error:
CLIENT:
Welcome to the Client mode
Please, enter the Server's IP Address and Port (eg. 192.128.192.0 1320)
127.0.0.1 2700
Connected to the server. Now you can send messages
Please, enter a message. Enter "FINISH" if you want to finish the connection
ECHO
client: connection closed ->: Success
(1 bytes)Closing the connection
SERVER:
Hello and welcome to the Server mode
Please, enter the Server's Port (eg. 1320)
2700
Server socket successfully configured
Server listening [Clients allowed: 5]
server: accept error: Bad address
Client implementation:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
/**
struct sockaddr{
uint8_t sa_len; // struct length
sa_family_t sa_family; //protocol family: AF_XXX
char sa_data[8]; //socket addr
}
*/
//void notConnected();
int main(){
struct sockaddr_in serv_addr; //port + ip_addr
int my_socket, tcp_port;
char serv_host_addr[30];
char buffer[1024], inbuff[1024];
int io_buffer;
printf("Welcome to the Client mode\n");
//CONFIGURING THE CONNECTION
my_socket = socket(AF_INET, SOCK_STREAM, 0);//(2)
if(my_socket < 0){
perror("client: socket() error ->");
exit(EXIT_FAILURE);
}
bzero(&serv_addr, sizeof(serv_addr));//(4)
printf("Please, enter the Server's IP Address and Port (eg. 192.128.192.0 1320) \n");
scanf("%s %d", serv_host_addr, &tcp_port);//(1)
serv_addr.sin_family = AF_INET ;
serv_addr.sin_port = htons(tcp_port);
if(inet_pton(AF_INET,serv_host_addr,&serv_addr.sin_addr) < 1){
perror("client: inet_pton() error ->");
exit(EXIT_FAILURE);
}
if((connect(my_socket, (struct sockaddr *) &serv_addr, sizeof(serv_addr) )) < 0)//(5)
{
perror("client: connect() error ->");
exit(EXIT_FAILURE);
}
//ONCE CONNECTED, START THE SENDING/RECEIVING
printf("Connected to the server. Now you can send messages\n");
bzero(&buffer, sizeof(buffer));
while(strcmp(buffer, "OK\n") != 0){
printf("Please, enter a message. Enter \"FINISH\" if you want to finish the connection\n");//(3)
bzero(&buffer, sizeof(buffer));
fgets(buffer, sizeof(buffer), stdin);
io_buffer = send(my_socket, buffer, strlen(buffer),0);//(6)
if(io_buffer < 0){
perror("client: send() error ->");
exit(EXIT_FAILURE);
}
printf("ECHO %s (%d bytes)", buffer, io_buffer);
//RECEIVE AND CHECK IF CONNECTION HAS BEEN CLOSED
io_buffer = recv(my_socket, buffer, sizeof(buffer),0);
if(io_buffer < 0){
perror("client: recv() error ->");
exit(EXIT_FAILURE);
}
else if(io_buffer == 0){ //THIS IS SERVER IS CLOSED
perror("client: connection closed ->");
break;
}
printf("ECHO %s (%d bytes)", buffer, io_buffer);
}
printf("Closing the connection \n");
for(int i=0; i < 5; i++){
printf(". ");
usleep(500000);
}
close(my_socket);
}
Server implementation:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define LISTENQ 5
int main()
{
struct sockaddr_in cli_addr, serv_addr;
char buffer[1024];
int serv_socket, cli_socket, clilen, io_buffer;
int tcp_port;
printf("Hello and welcome to the Server mode\n");
// ASKING FOR PORT NUMBER
if((serv_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0){
perror("server: can't open stream socket");
exit(EXIT_FAILURE);
}
printf("Please, enter the Server's Port (eg. 1320) \n");
scanf("%d", &tcp_port);
// CONFIGURING THE CONNECTION
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(tcp_port);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
// ASSIGNING A NAME TO THE SOCKET
if(bind(serv_socket,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0){
perror("server: can't assign a name to the socket");
exit(EXIT_FAILURE);
}
printf("Server socket successfully configured\n");
printf("Server listening [Clients allowed: %d]\n", LISTENQ);
if(listen(serv_socket, LISTENQ) < 0)
{
perror("server: fail to listen network");
exit(EXIT_FAILURE);
}
// READ & WRITE STREAM
while(1){
//returns a file descriptor for the client
cli_socket = accept(serv_socket,(struct sockaddr *) &cli_addr,(socklen_t *) sizeof(cli_addr));
if(cli_socket < 0){
perror("server: accept error");
exit(EXIT_FAILURE);
}
printf("Server successfully connected to Client\n");
while(1)
{
if ((io_buffer=recv(cli_socket,buffer,sizeof(buffer),0))<0){
perror("ERROR: recv");
exit(EXIT_FAILURE);
}
printf("\"%s\" received from client", buffer);
if(strcmp(buffer, "FINISH") == 0)
{
break;
}
if ((io_buffer=send(cli_socket,buffer,strlen(buffer),0))!=strlen(buffer)){
perror("ERROR: send");
exit(EXIT_FAILURE);
}
bzero(buffer, sizeof(buffer));
}
strcpy(buffer, "OK");
if ((io_buffer=send(cli_socket, buffer, strlen(buffer), 0)) != strlen(buffer)){
perror("ERROR: send");
exit(EXIT_FAILURE);
}
printf("\"OK\" message sent to the Client.\n");
printf("Closing the connection \n");
for(int i=0; i < 5; i++)
{
printf(". ");
usleep(500000);
}
close(cli_socket);
}
}
In your original question, your accept call looks like this:
cli_socket = accept(serv_socket,(struct sockaddr *) &cli_addr,
(socklen_t *) sizeof(cli_addr));
This passes "(socklen_t *) sizeof(cli_addr)" as the third parameter to accept. This is expected to be a pointer to the size of the structure. You should be passing in a pointer to a socklen_t containing the size of the structure passed as parameter two. The size you're currently passing in is being interpreted as an address, which is then causing your program to crash when it is referenced. The code should look like this:
socklen_t cli_addr_size = sizeof(cli_addr);
cli_socket = accept(serv_socket,(struct sockaddr *) &cli_addr,
&cli_addr_size);
I've added a Unix domain socket to a project I'm working on. The socket has a simple function, it simply broadcasts data that the code extracts from another device, the idea is that other applications will be able to read this data from the socket.
I've written a simple server code, and when I run the code on my laptop, using a Ubuntu 10.04 VM, it works perfectly well. However, when I copy the code over onto the embedded device I'm using the code fails, when my application tries to write to the socket the code exits.
In /var/log/messages I see the following messages:
Dec 2 15:12:17 box local1.info my-app[17338]: Socket Opened
Dec 2 15:12:17 box local1.err my-app[17338]: Socket Failed
Dec 2 15:12:17 box local1.err my-app[17338]: Protocol wrong type for socket
Dec 2 15:12:38 box local1.info ./server[17178]: accept failed: Invalid argument
Here is the server code:
#include <stdio.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include<syslog.h>
#define SV_SOCK_PATH "/tmp/rtig.sock" //path to be used by socket
#define BUF_SIZE 256 //Max length of string listened to
#define BACKLOG 5
int main(int argc, char *argv[]){
struct sockaddr_un addr;
int sfd, cfd; //File Descriptors for the server and the client
ssize_t numRead; //Length of the string read from the client.
u_int8_t buf[BUF_SIZE]; //String that reads messages
char plain[BUF_SIZE]; //Plain string for writing to the log
memset(plain, 0, sizeof plain); //blank out plain string
openlog(argv[0], LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); //Write the messages to the syslog
//---Declare socket--------------------------------------
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sfd!=0){
syslog(LOG_INFO, "socket success");
}
else{
syslog(LOG_INFO, "socket unsuccessful");
}
//--Test to see if there's already a socket at SV_SOCK_PATH, and remove it if there is.
if (remove(SV_SOCK_PATH) == -1 && errno !=ENOENT){
syslog(LOG_INFO, "error removing socket");
}
//-----------------------------------------------------------
//--blank out the socket address, then write the information to it
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SV_SOCK_PATH, sizeof(addr.sun_path)-1); //ensure path is null terminated
//----Bind the socket to the address-------------------------------------
if (bind(sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un))!=0){
syslog(LOG_INFO, "bind unsuccessful");
}
else{
syslog(LOG_INFO, "bind successful");
}
//------------------------------------------------------------------------
//-----Listen on the socket-----------------------------------------------
if (listen(sfd, BACKLOG) != 0){
syslog(LOG_INFO, "listen failed");
}
else{
syslog(LOG_INFO, "listen succeeded");
}
//-------------------------------------------------------------------------
//--------Accept messages on the socket------------------------------------
socklen_t csize;
while(1){
cfd = accept(sfd, (struct sockaddr *)&addr,&csize);
if (cfd < 0) {
syslog(LOG_INFO, "accept failed: %s", strerror(errno));
}
while ( (numRead=read(cfd, buf, BUF_SIZE)) > 0 ){
dump_packet(buf, numRead);
}
}
//-------------------------------------------------------------------------
//---code never gets here but this is how to close the log and the socket--
closelog();
close(cfd);
}
And here's a simple version of the client that connects to this server from my app:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SV_SOCK_PATH "/tmp/rtig.sock" //path to be used by socket
#define BACKLOG 5
int isDaemon = 1;
void etmlog(int level, char *message)
{
isDaemon == 1 ? syslog(level, message) : printf(message);
}
int main(){
struct sockaddr_un addr;
unsigned int sockfd;
ssize_t numRead;
if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) > 0) {
etmlog(LOG_INFO, "Socket Opened\n");
}
else {
etmlog(LOG_ERR, "Socket Failed:\n");
etmlog(LOG_ERR, strerror(errno));
exit(-1);
}
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SV_SOCK_PATH, sizeof(addr.sun_path) - 1); // -1 ensures null terminated string
if (connect
(sockfd, (struct sockaddr *)&addr,
sizeof(struct sockaddr_un)) == -1) {
etmlog(LOG_ERR, "Socket Failed\n");
etmlog(LOG_ERR, strerror(errno));
exit(1);
} else {
etmlog(LOG_INFO, "Socket Connection Successful\n");
}
while (1){
// some data is read into buf up here
if (write(sockfd, buf, rdlen) < 0) {
etmlog(LOG_ERR, "Write to Socket Failed:");
etmlog(LOG_ERR, strerror(errno));
}
}
close(sockfd);
return 0;
}
I appreciate that I've just posted a lot of code to read through, but I'd be very grateful if someone could give me a few pointers on this.
You are not using accept correctly. The third argument must be initialized to the size of the second argument, so that accept won't overflow it. See man accept.
This is a bit of an odd one. My code wasn't outputting what I thought it should. I added some print statements at various stages to see where it was going wrong. Still nothing.
So I added a printf statement at the start of main. That's where I got really confused.
So I presumed something funny was happening with the file descriptors. I changed the printf to a fprintf. Still nothing. Printing to stderr with fprintf does work! Why is this happening?
Removing all of the body from main except the initial print statement and the return does print.
Code
int main(void) {
fprintf(stdout, "STARTED!");
//Create an Internet domain socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
//If this fails exit and print the error
if (sockfd == -1) {
printf("Error %d, cannot create socket", errno);
return 1;
}
printf("SOCKET CREATED!");
//Creates a socket address
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = INADDR_ANY;
//Attempts to bind to the socket address, again prints to error if this fails.
if (bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
{
printf("Error %d, cannot bind", errno);
return 1;
}
//Starts Listening for a client
if (listen(sockfd, 1) == -1)
{
printf("Error %d, cannot listen", errno);
return 1;
}
//If all is successful, server is operational
while(1)
{
//Creates a file descripter for the connection
int connfd;
//And a socket address for the client
struct sockaddr_in cliaddr;
socklen_t cliaddrlen = sizeof(cliaddr);
//If a connection attempt is made accepts it.
connfd = accept(sockfd, (struct sockaddr *) &cliaddr, &cliaddrlen);
if (connfd == -1) {
//If the connection fails print an error
printf("Error %d, cannot accept connection", errno);
continue;
}
//Otherwise process the request
else {
printf("CONNECTED!");
char end;
end = 1;
while (end)
{
process_request(connfd);
end = 0;
}
}
close(connfd);
}
close(sockfd);
return 0;
}
Output is often buffered by the system. You can call fflush, but sometimes, depending on how the caching works, simply ending the output with a newline is sufficient. So try changing
fprintf(stdout, "STARTED!");
to
fprintf(stdout, "STARTED!\n");
And, if that doesn't help, to
fprintf(stdout, "STARTED!\n");
fflush(stdout)
(And stderr often isn't cached, as you want to see errors immediately.)
Finally, you will see output when the program finishes (as things are flushed then), which probably explains the rest of the behaviour.