簡體   English   中英

套接字中的數據發送錯誤

[英]Data sending error in socket

我在c中創建了簡單的服務器和客戶端。客戶端等待服務器直到服務器啟動。當我啟動服務器時,服務器和客戶端之間的數據傳輸符合我的期望。當我關閉服務器(不是客戶端)並再次重新啟動時服務器,從客戶端到服務器的第一個字符串不傳輸。然后,客戶端可以將字符串發送到服務器。因此,重新啟動服務器后,客戶端無法將第一個字符串傳輸到服務器。 這是我的客戶代碼(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;
        }
    }
}

這是我的服務器代碼(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);

}

這是client.config文件(用於客戶端獲取ip,服務器端口)

IP=192.168.3.17 PORT=7000

usb_trap=0

這是我第一次連接服務器時客戶端的輸出,

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

上面的輸出符合我的期望。

現在下面是重新連接服務器時客戶端的輸出(服務器斷開連接,然后再次啟動)

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

因此,在上面的輸出中,客戶端無法將第一個字符串寫入服務器。

客戶端信號處理程序:

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

這里所有可能是錯誤的錯誤。 沒有錯誤檢查。 您不能在信號處理程序中執行I / O。 您不能阻止信號處理程序。 您不需要“將null寫入服務器”。 退出應用程序將關閉套接字,或將其重置。

客戶:

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

不必要。 去掉。

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

無意義的消息。 您遇到了錯誤。 使用perror()或通過將strerror()合並到消息中來打印錯誤

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

錯誤的消息。 這種情況與前一種情況不同。 您已結束流。 對等體已斷開連接。 這樣說的。

    puts(received_data);

錯誤。 接收到的數據僅有效至n個字節。 正確的打印方法是通過printf("%.*s", n, received_data);

客戶端“接收處理程序”:

void *recieve_handler(void *socket_desc)

除了拼寫錯誤外,為什么它在不接收時被稱為接收處理程序? 並發送?

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

您可能在這里的意思是'\\0' ,因為代碼中還有許多其他反斜杠,但是memset()完全沒有必要。 去掉。

服務器信號處理程序:

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);
}

從頭到尾都是廢話。 您不能在信號處理程序中執行I / O; 您不能使用監聽套接字進行I / O; 您不能阻止信號處理程序; 而且您無需執行任何操作。 操作系統將關閉或重置套接字。 無論哪種方式,對等方都可以通過read()recv()的返回值來查找。

服務器循環:

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

不正確。 如果未將返回值存儲到變量中,則調用read()recv()永遠是不正確的。 您必須將其測試為-1,將其測試為零,否則將其用作接收的數據長度。 沒有變量,您將無法完成。 經過更正后,請參見您自己的客戶端代碼作為示例。

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

無效。 不能保證您會收到一個以空值結尾的字符串。 而且您還沒有先檢查EOS或錯誤。

        puts(recived_data);

無效的原因與上述客戶端中的puts()相同。

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

無效。 接收到的數據的長度由read()的返回值read()如果為正)而不是strlen(). 參見上面的討論。

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

請參閱上面有關此類隨意錯誤消息的討論。 完全沒有用。

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

這是什么? 去掉。

問題是您沒有正確取消線程。

采用

pthread_cancel(thread_id);

代替

pthread_cancel(&thread_id);

所以現在線程將被取消。該線程將不被使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM