繁体   English   中英

在Ubuntu上的PHP客户端和C服务器之间建立TCP套接字连接

[英]Establishing TCP socket connection between PHP client and C server on Ubuntu

我正在Ubuntu 16.04上编写一个简单的PHP客户端和C服务器程序。 在客户端,我用HTML创建了一个简单的图形用户界面,其中只有一个下拉框和一个提交按钮。 当我单击按钮时,将执行PHP客户端代码(尽管通过Apache服务器),但是客户端未连接到服务器,该服务器最初是在终端中启动的。

我想将下拉框的值传递给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);

?>

该代码充满了错误。

服务器

检查返回值

如果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是一个编译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()type参数)。

从线程处理程序访问套接字

您只为接受的套接字的文件描述符分配一个字节:

new_sock = malloc(1);

您可以将整数简单地转换为void指针

#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()

该代码显然“认为” pthread_create()函数返回线程ID。 没有。 成功时返回值为零,否则为错误代码。

从产生线程的那一刻起,您要负责其生命周期直至终止。 特别是,您应该等待子线程使用pthread_join()函数终止。 后者接受pthread_t ,它由pthread_create()初始化。 因此,您需要将pthread_t缓冲区存储在某个地方。 例如:

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

信号处理器

该程序将接受连接,直到超出线程限制为止,或者用户按Control - C或以其他方式终止该过程。 您应该附加信号处理程序,并实现线程间通信以正确停止accept连接等。由于这超出了问题的范围,我将其留给自学。

最后,不要在C中使用C ++注释。

Client.php

您正在将未定义变量$message长度$messagesocket_write

socket_write($socket, $selectedType, strlen($message));

由于该变量是未定义的,因此长度被评估为零,这意味着您什么也不发送到服务器。 为了完整起见,这是一个固定版本:

socket_write($socket, $selectedType, strlen($selectedType));

测试中

解决上述问题后,程序将响应用户输入:

1号航站楼

$ ./server
Socket created
bind done
Waiting for incoming connections...
Connection accepted
Server Received: 
test

2号航站楼

我已更改Client.php $selectedType以在CLI中进行测试:

$selectedType = isset($_POST['testType']) ? $_POST['testType'] : 'test';
$ php Client.php

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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