第一关
我不确定你看到了什么问题。我已经使用了你的代码(它的状态非常好——做得很好;我查看了很多代码,其中有很多更严重的问题)并编译并运行它,它似乎对我有用:
$ 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);
}
如果您仍然有问题,那么问题可能出在您的客户端代码中。如您所见,我使用netcat
( nc
) 作为您的客户的代理。请注意,“我们祝你圣诞快乐”被接受为有效命令,尽管引脚为 73,状态为 53。这可能不适用于真正的 LED。
请注意,我添加了错误检查malloc()
并分配了更正确的空间量(sizeof(int)
而不是仅 1 个字节)。我还确保报告的错误条件之后是或多或少适当的错误返回,而不是像没有发生错误一样继续。
此外,我还没有修复评论中突出显示的一些问题——检查write()
而不依赖空终止等。这些仍然应该得到解决。
我的测试是在带有 GCC 4.7.1 的 Mac OS X 10.7.5 上进行的:
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
,我得到了你所看到的不当行为,我认为:
$ 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);
}