2013-04-21 57 views
1

用戶輸入數據後,如果有意義,它會寫出輸入數據之前輸入的部分數據。我只包含一個片段,但任何人都可以看到爲什麼它會多次回覆?C Socket寫入次數太多

#include<stdio.h> 
#include<string.h> 
#include<stdlib.h> 
#include<sys/socket.h> 
#include<arpa/inet.h> //inet_addr 
#include<unistd.h> // write 

#include<pthread.h> // For Threading 

#include<wiringPi.h> 
void *connection_handler(void *); 
void lightLED(int pin,int status); 
int maxConnections = 1; 
int totalConnections = 0; 
int main(int argc , char *argv[]) 
{ 
    int socket_desc , new_socket , c, *new_sock; 
    struct sockaddr_in server , client; 
    char *message;  
    //Create socket 
    socket_desc = socket(AF_INET , SOCK_STREAM , 0); 
    if (socket_desc == -1) 
    { 
     printf("Could not create socket"); 
    } 

    //Prepare the sockaddr_in structure 
    server.sin_family = AF_INET; 
    server.sin_addr.s_addr = INADDR_ANY; 
    server.sin_port = htons(8888); 

    //Bind 
    if(bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0) 
    { 
     puts("bind failed"); 
    } 
    puts("bind done"); 

    //Listen 
    listen(socket_desc , 3); 

    //Accept and incoming connection 
    puts("Waiting for incoming connections..."); 
    c = sizeof(struct sockaddr_in); 
    while((new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c))) 
    { 
    if(new_socket > 0) 
    { 
     if(totalConnections < maxConnections){ 
     totalConnections++; 
    } 
     else 
     { 
     message = "Sorry Maximum Users Reached\n"; 
     write(new_socket,message,strlen(message)); 
     puts("Too many Users"); 
     close(new_socket); 
     continue; 
     } 
    } 
    puts("Connection Accepted"); 
    char *client_ip = inet_ntoa(client.sin_addr); 
    int client_port = ntohs(client.sin_port); 
    printf("ClientIP:%s\n",client_ip); 
    message = "Hello you have been accepted!\n"; 
    write(new_socket, message , strlen(message)); 

    pthread_t sniffer_thread; 
    new_sock = malloc(1); 
    *new_sock = new_socket; 

    if(pthread_create(&sniffer_thread, NULL , connection_handler , (void*) new_sock) <0) 
    { 
    perror("Could not create thread"); 
    return 1; 
    } 
    puts("Handler Assigned"); 
    } 

    if (new_socket<0) 
    { 
     perror("accept failed"); 
    return 1; 
    } 
    return 0; 
} 

void *connection_handler(void *socket_desc) 
{ 
    int sock = *(int*)socket_desc; 
    int read_size; 
    char *message , client_message[2000]; 

    message = "Greeting! I am your Connection Handler\n"; 
    write(sock , message,strlen(message)); 

    message = "What do you want to do\n"; 
    write(sock,message,strlen(message)); 

    while((read_size = recv(sock , client_message , 2000 , 0)) > 0) 
    { 
    write(sock , client_message , strlen(client_message)); 
    printf("User Entered:%s\n",client_message); 
    int pin = client_message[0]-'0'; 
    int status = client_message[1]-'0'; 
    lightLED(pin,status); 
    } 
    if(read_size == 0) 
    { 
    puts("Client Disconnected\n"); 
    fflush(stdout); 
    totalConnections--; 
    }else if(read_size == -1) 
    { 
    perror("recv Failed"); 
    } 

    free(socket_desc); 
    return 0; 
} 

void lightLED(int pin,int status) 
{ 
    char message; 
    if(wiringPiSetup() == -1){ 
    puts("wiringPi Error"); 
     exit(1); 
    } 

    //pinMode(pin,OUTPUT); 
    printf("Changing LED Pin- %d Status- %d\n",pin,status); 
    //digitalWrite(pin,status); 
} 
+4

您不檢查任何'write()'調用是否成功;這可能是一個問題。你會被告知剛讀出的信息的大小;然後使用'strlen()'寫回消息來確定大小。但是,您的寫入不包含空終止符,因此沒有理由期望讀取的數據包含空終止符,因此您可能正在編寫各種垃圾。 'printf()'也可能是打印垃圾。回顯客戶端發送的內容有些奇怪,保持不變,未經驗證。你不應該等到你檢查'lightLED()'後再回應嗎? – 2013-04-21 17:27:55

+0

好的。是的,就像我用它作爲測試的原因一樣,回覆發送的內容只是爲了測試它的作用。你會如何推薦使用收到的信息?如你所見,'lightLED()'需要2個整數。 – Lacko 2013-04-21 17:44:51

+1

'lightLED()'返回一個狀態,指示它是否能夠執行請求? LED號碼是否有效?請求是否有效?迴應收到的數據是好的;正確做得更好。日誌文件(或者標準輸出,與'printf()'一樣)是記錄細節的好地方。如果協議允許的話,回到客戶端是可以的 - 你知道你正在設計一個協議,不是嗎?設計你自己的一個優點是,你可以讓它按照你的需要工作,當然。您最多可以接受2000個字符;你只能使用2個字符。這是相當懸殊的。 – 2013-04-21 17:48:13

回答

2

第一遍

我不知道你看到的問題。我已經採取了你的代碼(這是在非常良好的狀態 - 做得好,我已經看了很多與它的許多問題變得更糟代碼),編譯並運行它,它似乎爲我工作:

$ nc localhost 8888 
Connection Accepted 
ClientIP:127.0.0.1 
Handler Assigned 
Hello you have been accepted! 
Greeting! I am your Connection Handler 
What do you want to do 
01 
User Entered:01 

Changing LED Pin- 0 Status- 1 
01 
21 
User Entered:21 

Changing LED Pin- 2 Status- 1 
21 
31 
User Entered:31 

Changing LED Pin- 3 Status- 1 
31 
we wish you a merry Christmas 
User Entered:we wish you a merry Christmas 

Changing LED Pin- 71 Status- 53 
we wish you a merry Christmas 
Client Disconnected 

$ 

的代碼運行是:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <pthread.h> 
//#include <wiringPi.h> 

void *connection_handler(void *); 
void lightLED(int pin, int status); 

int maxConnections = 1; 
int totalConnections = 0; 

int main(void) 
{ 
    int socket_desc, new_socket, c, *new_sock; 
    struct sockaddr_in server, client; 
    char *message; 

    socket_desc = socket(AF_INET, SOCK_STREAM, 0); 
    if (socket_desc == -1) 
    { 
     printf("Could not create socket"); 
     return 1; 
    } 

    server.sin_family = AF_INET; 
    server.sin_addr.s_addr = INADDR_ANY; 
    server.sin_port = htons(8888); 

    if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) 
    { 
     puts("bind failed"); 
     return 1; 
    } 
    puts("bind done"); 

    if (listen(socket_desc, 3) != 0) 
    { 
     perror("listen() failed"); 
     return 1; 
    } 

    puts("Waiting for incoming connections..."); 
    c = sizeof(struct sockaddr_in); 
    while ((new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c))) 
    { 
     if (new_socket > 0) 
     { 
      if (totalConnections < maxConnections) 
       totalConnections++; 
      else 
      { 
       message = "Sorry Maximum Users Reached\n"; 
       write(new_socket, message, strlen(message)); 
       puts("Too many Users"); 
       close(new_socket); 
       continue; 
      } 
     } 
     puts("Connection Accepted"); 
     char *client_ip = inet_ntoa(client.sin_addr); 
     //int client_port = ntohs(client.sin_port); 

     printf("ClientIP:%s\n", client_ip); 
     message = "Hello you have been accepted!\n"; 
     write(new_socket, message, strlen(message)); 

     pthread_t sniffer_thread; 
     new_sock = malloc(1 * sizeof(int));  // Oops! 
     if (new_sock == 0) { perror("out of memory"); return 1; } 
     *new_sock = new_socket; 

     if (pthread_create(&sniffer_thread, NULL, connection_handler, (void*) new_sock) <0) 
     { 
      perror("Could not create thread"); 
      return 1; 
     } 
     puts("Handler Assigned"); 
    } 

    if (new_socket<0) 
    { 
     perror("accept failed"); 
     return 1; 
    } 
    return 0; 
} 

void *connection_handler(void *socket_desc) 
{ 
    int sock = *(int*)socket_desc; 
    int read_size; 
    char *message, client_message[2000]; 

    message = "Greeting! I am your Connection Handler\n"; 
    write(sock, message, strlen(message)); 

    message = "What do you want to do\n"; 
    write(sock, message, strlen(message)); 

    while ((read_size = recv(sock, client_message, 2000, 0)) > 0) 
    { 
     write(sock, client_message, strlen(client_message)); 
     printf("User Entered:%s\n", client_message); 
     int pin = client_message[0]-'0'; 
     int status = client_message[1]-'0'; 
     lightLED(pin, status); 
    } 
    if (read_size == 0) 
    { 
     puts("Client Disconnected\n"); 
     fflush(stdout); 
     totalConnections--; 
    } 
    else if (read_size == -1) 
    { 
     perror("recv Failed"); 
    } 

    free(socket_desc); 
    return 0; 
} 

void lightLED(int pin, int status) 
{ 
// if (wiringPiSetup() == -1) 
// { 
//  puts("wiringPi Error"); 
//  exit(1); 
// } 

    printf("Changing LED Pin- %d Status- %d\n", pin, status); 
} 

如果仍然有問題,也許麻煩的是在客戶端代碼。如您所見,我使用netcatnc)作爲客戶的替代品。請注意,'我們祝你聖誕快樂'被認爲是一個有效的命令,儘管引腳爲73,狀態爲53.這可能不適用於真正的LED。

請注意,我爲malloc()添加了錯誤檢查並分配了更正確的空間量(sizeof(int)而不是僅1個字節)。我還確保報告的錯誤條件後面跟着一個或多或少的適當的錯誤返回,而不是像沒有錯誤發生一樣繼續。

此外,我還沒有解決一些在註釋中突出顯示的問題 - 檢查write()並且不依賴於空終止等。這些問題仍然應該解決。

我的測試是在Mac OS X 10.7.5與GCC 4.7.1:

gcc -O3 -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition server.c -o server 

第二次

另一個試運行 - 與顯示輸入的問題不是空終止:

$ nc localhost 8888 
Connection Accepted 
ClientIP:127.0.0.1 
Hello you have been accepted! 
Handler Assigned 
Greeting! I am your Connection Handler 
What do you want to do 
this is a long string - what will you do with it? 
User Entered:this is a long string - what will you do with it? 

Changing LED Pin- 68 Status- 56 
this is a long string - what will you do with it? 
01 
User Entered:01 
s is a long string - what will you do with it? 

Changing LED Pin- 0 Status- 1 
01 
s is a long string - what will you do with it? 
Client Disconnected 

$ 

當我與telnet運行它,而不是nc,時I g加時賽你看到的錯誤行爲,我認爲:

$ telnet localhost 8888 
Trying 127.0.0.1... 
Connection Accepted 
ClientIP:127.0.0.1 
Handler Assigned 
Connected to localhost. 
Escape character is '^]'. 
Hello you have been accepted! 
Greeting! I am your Connection Handler 
What do you want to do 
Would you like a biscuit? 
User Entered:Would you like a biscuit? 

Changing LED Pin- 39 Status- 63 
Would you like a biscuit? 
93 
User Entered:93 
d you like a biscuit? 

Changing LED Pin- 9 Status- 3 
93 
d you like a biscuit? 
Intriguing 
User Entered:Intriguing 
ke a biscuit? 

Changing LED Pin- 25 Status- 62 
Intriguing 
ke a biscuit? 
Bye 
User Entered:Bye 
guing 
ke a biscuit? 

Changing LED Pin- 18 Status- 73 
Bye 
guing 
ke a biscuit? 
User Entered:ye 
guing 
ke a biscuit? 

Changing LED Pin- -44 Status- 73 
ye 
guing 
ke a biscuit? 
^CUser Entered:????guing 
ke a biscuit? 

Changing LED Pin- -49 Status- -60 
User Entered:???guing 
ke a biscuit? 

Changing LED Pin- -49 Status- -53 
?guing 
ke a biscuit? 
User Entered:??guing 
ke a biscuit? 

...continued attempts with control-C (interrupt)... 
...and control-D (EOF) not producing anything useful... 

^] 
telnet> qConnection closed. 
Client Disconnected 

$ 

所以,telnet可能是誤導你...什麼都沒有了你的服務器,只需在客戶端(telnet)如你預期的不表現。

更新代碼

談話更新服務器代碼:

$ nc localhost 8888 
Connection Accepted 
ClientIP: 127.0.0.1 
Handler Assigned 
Hello you have been accepted! 
Greetings! I am your Connection Handler 
What do you want to do 
13 
User Entered:13 

Changing LED Pin 1 status 3 
13 
21 
User Entered:21 

Changing LED Pin 2 status 1 
21 
elephants? 
User Entered:elephants? 

Changing LED Pin 53 status 60 
elephants? 
21 
User Entered:21 

Changing LED Pin 2 status 1 
21 
quit 
User Entered:quit 

Changing LED Pin 65 status 69 
quit 
Client Disconnected 

$ 

更新服務器代碼

該版本注重長度和確保字符串空終止。

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <pthread.h> 
//#include <wiringPi.h> 

void *connection_handler(void *); 
void lightLED(int pin, int status); 
static void write_sock(int sock, const char *msg); 

int maxConnections = 1; 
int totalConnections = 0; 

int main(void) 
{ 
    int socket_desc, new_socket, c, *new_sock; 
    struct sockaddr_in server, client; 

    socket_desc = socket(AF_INET, SOCK_STREAM, 0); 
    if (socket_desc == -1) 
    { 
     printf("Could not create socket"); 
     return 1; 
    } 

    server.sin_family = AF_INET; 
    server.sin_addr.s_addr = INADDR_ANY; 
    server.sin_port = htons(8888); 

    if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) 
    { 
     puts("bind failed"); 
     return 1; 
    } 
    puts("bind done"); 

    if (listen(socket_desc, 3) != 0) 
    { 
     perror("listen() failed"); 
     return 1; 
    } 

    puts("Waiting for incoming connections..."); 
    c = sizeof(struct sockaddr_in); 
    while ((new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c))) 
    { 
     if (new_socket > 0) 
     { 
      if (totalConnections < maxConnections) 
       totalConnections++; 
      else 
      { 
       write_sock(new_socket, "Sorry Maximum Users Reached\n"); 
       puts("Too many Users"); 
       close(new_socket); 
       continue; 
      } 
     } 

     puts("Connection Accepted"); 
     char *client_ip = inet_ntoa(client.sin_addr); 
     //int client_port = ntohs(client.sin_port); 

     printf("ClientIP: %s\n", client_ip); 
     write_sock(new_socket, "Hello you have been accepted!\n"); 

     pthread_t sniffer_thread; 
     new_sock = malloc(1 * sizeof(int));  // Oops! 
     if (new_sock == 0) { perror("out of memory"); return 1; } 
     *new_sock = new_socket; 

     if (pthread_create(&sniffer_thread, NULL, connection_handler, (void *)new_sock) < 0) 
     { 
      perror("Could not create thread"); 
      return 1; 
     } 
     puts("Handler Assigned"); 
    } 

    if (new_socket < 0) 
    { 
     perror("accept failed"); 
     return 1; 
    } 
    return 0; 
} 

// Avoid repetition - use functions! 
static void write_sock(int sock, const char *msg) 
{ 
    int len = strlen(msg); 
    if (write(sock, msg, len) != len) 
    { 
     perror("short write on socket"); 
     exit(1); 
    } 
} 

void *connection_handler(void *socket_desc) 
{ 
    int sock = *(int*)socket_desc; 
    int read_size; 
    char client_message[2000]; 

    write_sock(sock, "Greetings! I am your Connection Handler\n"); 
    write_sock(sock, "What do you want to do\n"); 

    while ((read_size = recv(sock, client_message, 2000, 0)) > 0) 
    { 
     client_message[read_size] = '\0'; 
     write_sock(sock, client_message); 
     printf("User Entered:%s\n", client_message); 
     int pin = client_message[0]-'0'; 
     int status = client_message[1]-'0'; 
     lightLED(pin, status); 
    } 

    if (read_size == 0) 
    { 
     puts("Client Disconnected\n"); 
     fflush(stdout); 
     totalConnections--; 
    } 
    else if (read_size == -1) 
    { 
     perror("recv Failed"); 
    } 

    free(socket_desc); 
    return 0; 
} 

void lightLED(int pin, int status) 
{ 
// if (wiringPiSetup() == -1) 
// { 
//  puts("wiringPi Error"); 
//  exit(1); 
// } 
    printf("Changing LED Pin %d status %d\n", pin, status); 
} 

注意使用功能write_sock()的封裝重複碼(其具有僅需要代碼側益處寫一次,所以可以正確的每次使用的時間)。

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <pthread.h> 
//#include <wiringPi.h> 

void *connection_handler(void *); 
void lightLED(int pin, int status); 
static void write_sock(int sock, const char *msg); 

int maxConnections = 1; 
int totalConnections = 0; 

int main(void) 
{ 
    int socket_desc, new_socket, c, *new_sock; 
    struct sockaddr_in server, client; 

    socket_desc = socket(AF_INET, SOCK_STREAM, 0); 
    if (socket_desc == -1) 
    { 
     printf("Could not create socket"); 
     return 1; 
    } 

    server.sin_family = AF_INET; 
    server.sin_addr.s_addr = INADDR_ANY; 
    server.sin_port = htons(8888); 

    if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) 
    { 
     puts("bind failed"); 
     return 1; 
    } 
    puts("bind done"); 

    if (listen(socket_desc, 3) != 0) 
    { 
     perror("listen() failed"); 
     return 1; 
    } 

    puts("Waiting for incoming connections..."); 
    c = sizeof(struct sockaddr_in); 
    while ((new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c))) 
    { 
     if (new_socket > 0) 
     { 
      if (totalConnections < maxConnections) 
       totalConnections++; 
      else 
      { 
       write_sock(new_socket, "Sorry Maximum Users Reached\n"); 
       puts("Too many Users"); 
       close(new_socket); 
       continue; 
      } 
     } 

     puts("Connection Accepted"); 
     char *client_ip = inet_ntoa(client.sin_addr); 
     //int client_port = ntohs(client.sin_port); 

     printf("ClientIP: %s\n", client_ip); 
     write_sock(new_socket, "Hello you have been accepted!\n"); 

     pthread_t sniffer_thread; 
     new_sock = malloc(1 * sizeof(int));  // Oops! 
     if (new_sock == 0) { perror("out of memory"); return 1; } 
     *new_sock = new_socket; 

     if (pthread_create(&sniffer_thread, NULL, connection_handler, (void *)new_sock) < 0) 
     { 
      perror("Could not create thread"); 
      return 1; 
     } 
     puts("Handler Assigned"); 
    } 

    if (new_socket < 0) 
    { 
     perror("accept failed"); 
     return 1; 
    } 
    return 0; 
} 

// Avoid repetition - use functions! 
static void write_sock(int sock, const char *msg) 
{ 
    int len = strlen(msg); 
    if (write(sock, msg, len) != len) 
    { 
     perror("short write on socket"); 
     exit(1); 
    } 
} 

void *connection_handler(void *socket_desc) 
{ 
    int sock = *(int*)socket_desc; 
    int read_size; 
    char client_message[2000]; 

    write_sock(sock, "Greetings! I am your Connection Handler\n"); 
    write_sock(sock, "What do you want to do\n"); 

    while ((read_size = recv(sock, client_message, 2000, 0)) > 0) 
    { 
     client_message[read_size] = '\0'; 
     write_sock(sock, client_message); 
     printf("User Entered:%s\n", client_message); 
     int pin = client_message[0]-'0'; 
     int status = client_message[1]-'0'; 
     lightLED(pin, status); 
    } 

    if (read_size == 0) 
    { 
     puts("Client Disconnected\n"); 
     fflush(stdout); 
     totalConnections--; 
    } 
    else if (read_size == -1) 
    { 
     perror("recv Failed"); 
    } 

    free(socket_desc); 
    return 0; 
} 

void lightLED(int pin, int status) 
{ 
// if (wiringPiSetup() == -1) 
// { 
//  puts("wiringPi Error"); 
//  exit(1); 
// } 
    printf("Changing LED Pin %d status %d\n", pin, status); 
} 
+0

謝謝你,先生。我會嘗試。 我一直在做它在Telnet,當我嘗試它在NC它運作良好。你是否喜歡在Telnet上嘗試它,你可能會發現當你關閉連接客戶端時,服務器會收到另外兩條消息,其中包含數字-44 – Lacko 2013-04-21 18:42:53

+1

-44是'^ D - '0''; 'telnet'正在發送未解釋的控制-D。 – 2013-04-21 18:56:58

+0

啊,好吧,現在生活的光明就是..telnet。感謝您的幫助 – Lacko 2013-04-21 19:48:29