我正在Ubuntu 16.04上编写一个简单的PHP客户端和C服务器程序。在客户端,我用HTML制作了一个简单的图形用户界面,其中只有一个下拉框和一个提交按钮。当我点击按钮时,会执行PHP客户端代码(虽然是Apache服务器),但是客户端没有连接到最初在终端中启动的服务器。
我想将下拉框的值传递给C服务器,无论用户从下拉列表中选择什么。请帮我弄清楚我的代码有什么问题。
Server.c
//All Libraries are present including pthread
#define BUFFER_SIZE 1024
//the thread function
void *connection_handler(void *);
int main(int argc , char *argv[])
{
int socket_desc , client_sock , 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");
}
puts("Socket created");
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)
{
perror("bind failed. Error");
return 1;
}
puts("bind done");
listen(socket_desc , 3);
c = sizeof(struct sockaddr_in);
int threadID;
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
puts("Connection accepted");
pthread_t sniffer_thread;
new_sock = malloc(1);
*new_sock = client_sock;
threadID=pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock);
if( threadID < 0)
{
perror("could not create thread");
return 1;
}
puts("Handler assigned");
}
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
return 0;
}
void *connection_handler(void *socket_desc)
{
int read_size;
char *serverErrorMsg="Invalid Details!";
char client_message[2000],client_poll[2000];
int sock = *(int*)socket_desc;
//Receive a message from client
if( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
{
puts("Server Received: ");
puts(client_message);
}
else
{
write(sock , serverErrorMsg , strlen(serverErrorMsg));
}
free(socket_desc);
return 0;
}
Client.php
<?php
error_reporting(E_ALL);
$host = "127.0.0.1";
$port = 8888;
// create socket
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
// connect to server
$result = socket_connect($socket, $host, $port) or die("Could not connect to server\n");
// sending test type to server
$selectedType = $_POST['testType']; //html drop down with name='testType'
socket_write($socket, $selectedType, strlen($message)) or die("Could not send data to server\n");
socket_close($socket);
?>
答案 0 :(得分:0)
代码中充满了错误。
检查返回值
如果socket()
失败,您只会向标准输出打印一条消息。程序继续以无效描述符运行:
socket_desc = socket(AF_INET, SOCK_STREAM, 0)
if (socket_desc == -1) {
printf("Could not create socket");
}
标准输入/输出
您应该将错误打印到标准错误描述符,然后是abort()
,或者使用非零退出代码退出,例如:
#include <errno.h>
#include <string.h>
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1) {
fprintf(stderr, "socket() failed: %s\n", strerror(errno));
exit(1);
}
<强> -Wall
强>
显然,您还没有编写带有警告的代码:
a.c:xxx:yy warning: unused variable ‘client_poll’ [-Wunused-variable]
始终使用-Wall
进行编译。
<强> sizeof
强>
没有必要将sizeof
的结果存储在内存中,因为sizeof
是编译时运算符:
/* Don't do this. Use a macro, if you want to shorten sizeof expression */
c = sizeof(struct sockaddr_in)
关闭套接字
当会话完成时,应该关闭套接字描述符:
close(socket_desc);
否则,请使用SOCK_CLOEXEC
标记(socket()
的{{1}}参数)。
从线程处理程序访问套接字
您只为接受的套接字的文件描述符分配单个字节:
type
您可以简单地cast integer to void pointer:
new_sock = malloc(1);
即使您想使用#include <stdint.h>
void *connection_handler(void *socket_desc)
{
int sock = (intptr_t) socket_desc;
/* ... */
}
threadID = pthread_create(&sniffer_thread, NULL,
connection_handler, (void *)(intptr_t) new_sock);
,也可以使用malloc
运算符:
sizeof
关于/* Allocates memory for an integer */
new_sock = malloc(sizeof(int));
代码显然“认为”pthread_create()
函数返回一个线程ID。它没有。成功时返回值为零,否则为错误代码。
从您生成线程的那一刻起,您就要对其生命周期负责,直到它终止为止。特别是,您应该等待子线程使用pthread_create()
函数终止。后者接受pthread_join()
,由pthread_t
初始化。所以你需要在某处存储pthread_create()
个缓冲区。 E.g:
pthread_t
信号处理程序
程序接受连接,直到线程限制超过,或者用户按 Control - C ,或以其他方式终止进程。您应该附加信号处理程序,并实施线程间通信以正确阻止int rc, i = 0;
const int MAX_THREADS = 10;
pthread_t *threads = calloc(sizeof(pthread_t), MAX_THREADS);
struct sockaddr_storage their_addr;
socklen_t addr_size;
puts("Waiting for incoming connections...");
addr_size = sizeof their_addr;
while ((client_sock = accept(socket_desc, (struct sockaddr *)&their_addr, &addr_size)) > 0) {
puts("Connection accepted");
if (i >= MAX_THREADS) {
fprintf(stderr, "Max threads limit exceeded: %d, closing client socket\n", i);
close(client_sock);
break;
}
rc = pthread_create(&threads[i++], NULL,
connection_handler, (void *)(intptr_t) client_sock);
if (rc) {
perror("could not create thread");
break;
}
}
if (threads) {
int i;
for (i = 0; i < MAX_THREADS; i++) {
if (threads[i])
pthread_join(threads[i], NULL);
}
free(threads);
}
连接等。由于这超出了问题的范围,我将留下进行自学。
最后,不要在C中使用C ++注释。
您将未定义变量accept
的长度传递给$message
:
socket_write
由于变量未定义,因此长度计算为零,这意味着您不向服务器发送任何内容。这是一个固定版本,为了完整性:
socket_write($socket, $selectedType, strlen($message));
修复上述内容后,程序会响应用户输入:
1号航站楼
socket_write($socket, $selectedType, strlen($selectedType));
2号航站楼
我在$ ./server
Socket created
bind done
Waiting for incoming connections...
Connection accepted
Server Received:
test
中更改了$selectedType
以便在CLI中进行测试:
Client.php
$selectedType = isset($_POST['testType']) ? $_POST['testType'] : 'test';