简体   繁体   中英

Data sending error in socket

I have made simple server and client in c.Client waits for server until server is started.When i start the server data transmission between server and client is happening as per my expectation.When i close the server(not client) and again restarts the server,the first string from client to server is not transmitting.and then afterwards the client can send strings to server.So after restarting server client can't transmit first string to server. Here is my client code(client.c),

 /*header*/
#include<signal.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
/*macros*/
/*size of the buffer*/
#define DATA_SIZE 200
/*function for thread*/
void *recieve_handler(void *);
/*stores the id of main thread*/
pthread_t main_id;
/*socket variable*/
int sockfd=0;
/*specifies the port number*/
#define PORT 5000
/*lenth of ip*/
#define LENGTH_OF_IP 100
int quit = 1;
void signal_handler(int n)
{
    /*write null to server*/
    write(sockfd,"",2);
    /*close socket*/
    close(sockfd);
    printf("Exiting from applicationn");
    exit(0);
}
int main(int argc, char *argv[])
{
    /*buffer to send and receive*/
    char received_data[DATA_SIZE],send_data[DATA_SIZE],server_ip[LENGTH_OF_IP],buf[DATA_SIZE]
    ,user_name[DATA_SIZE];
    /*declare pointer for client config file*/
    FILE* config_file;
    /*flags*/
    int clear = 1,server_port,usb_trap_on,n;
    /*declaring socket object*/
    struct sockaddr_in serv_addr;
    /*thread declaration*/
    pthread_t thread_id;
    /*welcome messsage*/
    printf("This is clientn");
    printf("Enter somethingn");
    printf("Server echos back the datan");
    /*open client configuration file*/
    if ((config_file = fopen("client.config","rw+")) == NULL)
    {
        printf("Could not open client config filen");
        return 1;
    }
    /*parsing the file*/
    while (fgets(buf, sizeof buf, config_file) != NULL) {
        if (sscanf(buf,"IP=%s PORT=%d",server_ip,&server_port) == 2)
        printf("%s %dn",server_ip,server_port);
        if (fscanf(config_file,"usb_trap=%d",&usb_trap_on) == 1)
        printf("usb flag is %dn",usb_trap_on);
    }
    /*create the socket*/
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
        printf("n Error : Could not create socket n");
        return 1;
    }
    /*By setsockopt kernal will release the socket
    *if it is in use*/
    if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&clear,sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }
    /*inialize all the variable of object serv_addr with 0*/
    memset(&serv_addr, '0', sizeof(serv_addr));
    /*AF_INET refers to addresses from the internet*/
    serv_addr.sin_family = AF_INET;
    /*specifies port address
    *and The htons() function makes sure that numbers are stored
    *in memory in network byte order, which is with the most
    *significant byte first*/
    serv_addr.sin_port = htons(server_port);
    /* inet_pton - convert IPv4 and IPv6 addresses from text to binary form
    * it returns 0 when coversion is unsucessful*/
    if(inet_pton(AF_INET, server_ip, &serv_addr.sin_addr)<=0){
        printf("n inet_pton error occuredn");
        return 1;
    }
    /*connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))
    *if connection is established then the memory for server will be
    *allocated in client's memory
    *and strting address of that memory is stored in scokfd
    *i will return negative value if operation fails. */
    while(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
        printf("Wating for server to connectn");
        sleep(1);
    }
    printf("Connection is donen");
    printf("enter somethingn");
    /*signal handling*/
    signal(SIGTSTP,signal_handler);
    /*create the thread to receive data*/
    if( pthread_create( &thread_id , NULL , recieve_handler , (void*)&sockfd) < 0) {
        perror("could not create thread");
        return 1;
    }
    while(1) {
        /*clear the buffer*/
        memset(received_data,0,DATA_SIZE);
        /*read from server*/
        n = read(sockfd,received_data,sizeof(received_data));
        /*if read error is occurred*/
        if (n < 0) {
            printf("Can't read received_datan");
            break;
            pthread_exit(&n);
        }
        if(n == 0) {
            printf("Can't read received_datan");
            break;
        }
        puts(received_data);
    }
    pthread_cancel(&thread_id);
    /*close socket*/
    if(!close(sockfd))
    printf("Socket is closedn");
    printf("Server is sutdown!!!!!!!!!!!!!n");
    system("./client");
    return 0;
}
void *recieve_handler(void *socket_desc)
{
    /*received data buffer*/
    char send_data[DATA_SIZE];
    /*status flag*/
    int n;
    /*if pointer is empty*/
    if(socket_desc == NULL) {
        printf("socket_desc is NULLn");
        n = 0;
        pthread_exit(&n);
    }
    /*socket number*/
    int sock = *(int*)socket_desc;
    /*infinite loop*/
    while (1){
        /*clear buffer*/
        memset(send_data, '0', sizeof(send_data));
        /*get data from user*/
        gets(send_data);
        if((write(sock, send_data, strlen(send_data)+1)) == -1)
        {
            /*write data to server*/
            printf("could not writen");
            break;
        }
    }
}

here is my server code(server.c),

/*header*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h> 
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h> 

/*macros*/

/*maximum client that can be connected to server*/
#define MAX_CLIENT 10

/*size of the buffer*/
#define DATA_SIZE 200

/*specifies the port number*/
#define PORT 7000

int listenfd;

void signal_handler(int n)

{


printf("In handler\n");
char recived_data[DATA_SIZE];
 write(listenfd,"\0",2);

read(listenfd, recived_data, sizeof(recived_data));/*write null to server*/

    write(listenfd,"\0",2);


    /*close socket*/

    close(listenfd);



    printf("Exiting from application\n");



    exit(0);

}

int main(int argc, char *argv[])
{


    /*signal handling*/
    signal(SIGTSTP,signal_handler);

    /*to store the recived data*/
    char recived_data[DATA_SIZE];   

    /*sockaddr_in is a structure defined in netinet/in.h file.we are creating object of that
     *strucure. */
    struct sockaddr_in serv_addr;

    /*flags*/
    int  connfd = 0 , clear = 1 ;

    /*welcome message*/
    printf("This simple server\n");
    printf("It will echo data to client\n");
    printf("If quit is recived from client then server will be existed\n");

    /*Created socket*/
    if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
        printf("Can't create socket\n");
    }

    /*By setsockopt kernal will release the socket
     *if it is in use*/
    if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&clear,sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }

    /*AF_INET refers to addresses from the internet*/
    serv_addr.sin_family = AF_INET;

    /*tells that any client can connect*/
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    /*specifies port address 
     *and The htons() function makes sure that numbers are stored 
     *in memory in network byte order, which is with the most 
     *significant byte first*/
    serv_addr.sin_port = htons(PORT);

    /*specifies  port and adress of the socket*/ 
    bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

    /*it will listen for connection
     *MAX_CLIENT specifies the maximum client server can handle*/
    listen(listenfd, MAX_CLIENT); 

    /*accept will assign the memory to client in server's memory area.here 
     *connfd has starting adress of  assigned memory to client in server 
     *memory.*/
    connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);


    /*inet_ntoa(serv_addr.sin_addr) will return the adress of client*/
    printf("[Server] Server has got connected from %s.\n", inet_ntoa(serv_addr.sin_addr));


        printf("server waiting\n");

    while(1){

        /*read the data from memory and put in buffer*/
        if(read(connfd, recived_data, sizeof(recived_data))){

            /*if quit is recived then break the loop*/
            if(!strcmp(recived_data,"quit"))
                break; 

            /*put data on screen*/
            puts(recived_data);

            /*echo the data back to client*/
            if(write(connfd,recived_data,strlen(recived_data)+1) == -1)
                break;  

        }

        else
        {
            printf("Could not read\n");
        }
    }

    read(connfd, recived_data, sizeof(recived_data));    
    printf("server exiting\n");

    /*close socket*/
    close(connfd);

    return(0);

}

here is client.config file(which is used be client to get ip,port of server)

IP=192.168.3.17 PORT=7000

usb_trap=0

This is my output of client when server is first time connected,

This is client
Enter something
Server echos back the data
192.168.3.17 7000
usb flag is 0
Wating for server to connect
Wating for server to connect
Connection is done
enter something
hello
hello
i am jay
i am jay

Above output is as per my expectation.

Now below is my output of client when server is reconnected(server is disconnected ,and then started again)

Socket is closed
Server is sutdown!!!!!!!!!!!!!
This is client
Enter something
Server echos back the data
192.168.3.17 7000
usb flag is 0
Wating for server to connect
Wating for server to connect
Wating for server to connect
Wating for server to connect
Connection is done
enter something
hello
could not write
jay
jay

So in above output client can't write first string to server.

Client signal handler:

void signal_handler(int n)
{
    /*write null to server*/
    write(sockfd,"",2);
    /*close socket*/
    close(sockfd);
    printf("Exiting from applicationn");
    exit(0);
}

Everything wrong here that could be wrong. No error checking. You can't do I/O in signal handlers. You can't block in signal handlers. You don't need to 'write null to server'. Exiting the application will close the socket, or reset it.

Client:

while(1) {
    /*clear the buffer*/
    memset(received_data,0,DATA_SIZE);

Unnecessary. Remove.

    if (n < 0) {
        printf("Can't read received_datan");

A pointless message. You got an error. Print the error, with perror() , or by incorporating strerror() into the message.

    if(n == 0) {
        printf("Can't read received_datan");

An incorrect message. This situation is not the same as the previous one. You got end of stream. The peer has disconnected. Say so.

    puts(received_data);

Wrong. The data received is only valid up to n bytes. The correct way to print it is via printf("%.*s", n, received_data);

Client 'receive handler':

void *recieve_handler(void *socket_desc)

Apart from the mis-spelling, why is this called a receive handler when it doesn't receive? and does send?

 memset(send_data, '0', sizeof(send_data));
 /*get data from user*/
 gets(send_data);

You probably meant '\\0' here, as there are numerous other backslashes missing from your code, but the memset() is completely unnecessary. Remove.

Server signal handler:

void signal_handler(int n)
{
    printf("In handler\n");
    char recived_data[DATA_SIZE];
    write(listenfd,"\0",2);
    read(listenfd, recived_data, sizeof(recived_data));/*write null to server*/
    write(listenfd,"\0",2);
    /*close socket*/
    close(listenfd);
    printf("Exiting from application\n");
    exit(0);
}

This is all nonsense from start to finish. You can't do I/O in a signal handler; you can't do I/O with a listening socket; you can't block in a signal handler; and you don't need to do any of it. The operating system will either close or reset the socket. Either way the peer will find out via the return value of read() or recv() .

Server loop:

    if(read(connfd, recived_data, sizeof(recived_data))){

Incorrect. It is never correct to call read() or recv() without storing the return value into a variable. You have to test it for -1, test it for zero, and otherwise use it as the length of data received. You can't accomplish that without a variable. See your own client code for an example, after my corrections.

        if(!strcmp(recived_data,"quit"))

Invalid. There is no guarantee that you will receive a null-terminated string. And you haven't checked for EOS or an error first.

        puts(recived_data);

Invalid for the same reason as the puts() in the client as discussed above.

        if(write(connfd,recived_data,strlen(recived_data)+1) == -1)

Invalid. The length of the data received is given by the return value of read() if positive, not by strlen(). See discussion above.

    else
    {
        printf("Could not read\n");
    }

See discussion above about indiscriminate error messages like this. No use at all.

read(connfd, recived_data, sizeof(recived_data));    

What is this? Remove.

Problem is that you are not canceling the thread properly.

Use

pthread_cancel(thread_id);

instead of

pthread_cancel(&thread_id);

So now thread will be canceled.and that thread will not be lived.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM