- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
所以我有一个非常简单的多服务器-客户端应用程序 (Linux)。我想为初学者做的是连接到服务器接收来自它的消息并将消息写入服务器然后回声。
问题是在连接上而不是来自服务器的问候消息,客户端准备将消息键入终端 - 没有问候消息。输入我想要的任何消息后,我会收到问候消息!我在这里做错了什么?代码如下。
服务器.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <pthread.h>
#include <netdb.h>
#include <netinet/in.h>
int server(int client_socket);
void* handle_connection(void* inc);
int main(int argc, char* argv[])
{
int socket_fd;
int client_socket_fd;
int port_number;
int client_length;
int * new_sock;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
char buffer[256];
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(socket_fd < 0) {
perror("Error opening socket!");
exit(1);
}
/* Initialize socket structure */
port_number = 1234;
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr= INADDR_ANY;
serv_addr.sin_port = htons(port_number);
/* Binding */
if(bind(socket_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("Error on binding!");
exit(1);
}
listen(socket_fd, 10);
client_length = sizeof(cli_addr);
while(client_socket_fd = accept(socket_fd, (struct sockaddr*) &cli_addr, &client_length)) {
pthread_t thread_id;
new_sock = malloc(sizeof(client_socket_fd));
*new_sock = client_socket_fd;
if(pthread_create(&thread_id, NULL, handle_connection, (void*) new_sock)) {
perror("could not create thread");
exit(1);
}
pthread_join(thread_id, NULL);
}
if(client_socket_fd < 0) {
perror("Error on accept client");
exit(1);
}
return 0;
}
void* handle_connection(void* inc)
{
int socket_fd = *(int *) inc;
int message_size;
char *message;
char buffer[256];
message = "You have been connected\n";
write(socket_fd, message, strlen(message));
message = "I will repeat what you type\n";
write(socket_fd, message, strlen(message));
while((message_size = recv(socket_fd, buffer, sizeof(buffer)/sizeof(buffer[0]), 0)) > 0) {
write(socket_fd, buffer, strlen(buffer));
}
if(message_size == 0) {
puts("Client disconnected");
fflush(stdout);
}
else if(message_size == -1) {
perror("Reading back from client failed");
}
free(inc);
return 0;
}
客户端.c
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
int main(int argc, char* argv[])
{
int socket_fd, port_number;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if(argc<2) {
fprintf(stderr,"Incorrect arguments input\n");
exit(0);
}
//port_number = atoi(argv[2]);
port_number = 1234;
server = gethostbyname(argv[1]);
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(socket_fd < 0) {
perror("Error opening socket");
exit(1);
}
bzero((char*) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port_number);
bcopy((char*) server->h_addr,(char *) &serv_addr.sin_addr.s_addr,sizeof(server->h_length));
if(connect(socket_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("Error connecting");
exit(1);
}
while(1) {
bzero(buffer, sizeof(buffer)/sizeof(buffer[0]));
printf("Enter the message: ");
bzero(buffer, sizeof(buffer)/sizeof(buffer[0]));
fgets(buffer, sizeof(buffer)/sizeof(buffer[0]) - 1, stdin);
if(send(socket_fd, buffer, strlen(buffer), 0) < 0) {
perror("Error sending message");
exit(1);
}
bzero(buffer, sizeof(buffer)/sizeof(buffer[0]));
if(recv(socket_fd, buffer, sizeof(buffer), 0) < 0) {
perror("Error reading back from server");
exit(1);
}
printf("Server reply: ");
printf("%s",buffer);
}
close(socket_fd);
return 0;
}
示例中的服务器回复应该是:hej。
最佳答案
The problem is that on connection instead of greetings message from server, client is ready to type the message ito the terminal - there is no greetings message.
这是因为在使用 recv()
获取问候语并将其显示给用户之前,您正在读取用户输入。
After typing whatever message I want I get echoed back with the greetings message!
这是因为您正在获取/显示调用之后的问候语fgets()
.
代码中有很多错误。我会指出最大的那些。
pthread_create()
之后立即调用 pthread_join()
。那是阻止新连接(即进一步的 accept()
)。应该这样做在循环之外。在这种情况下,您需要一些线程 ID 存储空间。为了示例:const int thread_pool_step = 10;
int thread_pool_size = thread_pool_step;
pthread_t *thread_ids = malloc(thread_pool_size * sizeof(pthread_t));
memset(thread_ids, 0, thread_pool_size * sizeof(pthread_t));
int thread_index = -1;
while (!do_shutdown)
{
/* ... */
if (++thread_index >= thread_pool_size)
{
thread_pool_size += thread_pool_step;
thread_ids = realloc(thread_ids, thread_pool_size * sizeof(pthread_t));
if (thread_ids == NULL)
{
fprintf(stderr, "failed to realloc thread pool: %s\n",
strerror(errno));
abort();
}
}
pthread_create(&thread_ids[thread_index++], NULL,
handle_connection, (void*) new_sock);
}
while (--thread_index >= 0)
{
if (thread_ids[thread_index])
pthread_join(thread_ids[thread_index], NULL);
}
if (thread_ids != NULL)
free(thread_ids);
enum {
INIT_STATE,
READY_STATE
} serv_state = INIT_STATE;
#define check_serv_state(str, st) \
(strncmp(str, #st, sizeof(#st) - 1) == 0)
for (;;)
{
bzero(buffer, sizeof(buffer)/sizeof(buffer[0]));
rc = recv(socket_fd, buffer, sizeof(buffer), 0);
/* ... */
if (serv_state == INIT_STATE)
{
char *part = strtok(buffer, "\n");
do
{
if (check_serv_state(part, READY))
{
printf("The server is ready for the chat\n");
serv_state = READY_STATE;
}
else
printf("Server: [[[%s]]]\n", part);
}
while ((part = strtok(NULL, "\n")));
if (serv_state != READY_STATE)
continue;
}
else
printf("Server reply: %s", buffer);
/* ... */
printf("Enter the message: ");
/* ... */
}
volatile sig_atomic_t do_shutdown = 0; /* global */
static void
sigterm_handler(int sig)
{
printf("Caught signal %d. Leaving...\n", sig);
do_shutdown = 1;
}
/* ... */
struct sigaction a;
a.sa_handler = sigterm_handler;
a.sa_flags = 0;
sigemptyset(&a.sa_mask);
sigaction(SIGINT, &a, NULL);
sigaction(SIGQUIT, &a, NULL);
sigaction(SIGTERM, &a, NULL);
/* Check do_shutdown in the loops */
while (!do_shutdown) { /* ...recv(), accept(), etc. */ }
请注意,如果不使用 mutual exclusion,从异步上下文(信号处理程序、线程处理程序[尤其是])访问全局变量通常是不安全的.
下面是应用了修复的完整代码:
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <netdb.h>
#include <netinet/in.h>
volatile sig_atomic_t do_shutdown = 0;
static void
sigterm_handler(int sig)
{
printf("Caught signal %d. Leaving...\n", sig);
do_shutdown = 1;
}
static void
send_message(int socket_fd, const char *message)
{
int rc;
int message_size = strlen(message);
do
{
rc = send(socket_fd, message, message_size, 0);
if (rc == -1)
{
fprintf(stderr, "send() failed: %s\n", strerror(errno));
abort();
}
}
while (rc < message_size && !do_shutdown);
}
static void *
handle_connection(void *inc)
{
int socket_fd = *(int *)inc;
int message_size;
char *message;
char buffer[256];
message = "You have been connected\n";
send_message(socket_fd, message);
message = "I will repeat what you type\n";
send_message(socket_fd, message);
message = "READY\n";
send_message(socket_fd, message);
while (!do_shutdown)
{
memset(buffer, 0, sizeof(buffer));
message_size = recv(socket_fd, buffer, sizeof(buffer) / sizeof(buffer[0]), 0);
if (message_size > 0)
send_message(socket_fd, buffer);
else if (message_size == -1)
{
fprintf(stderr, "recv() failed: %s\n", strerror(errno));
break;
}
else if (message_size == 0)
{
puts("Client disconnected");
fflush(stdout);
break;
}
}
free(inc);
return 0;
}
int
main(int argc, char* argv[])
{
int socket_fd;
int client_socket_fd;
int port_number;
socklen_t client_length;
int *new_sock;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd < 0)
{
perror("Error opening socket!");
exit(1);
}
/* Initialize socket structure */
port_number = 12345;
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr= INADDR_ANY;
serv_addr.sin_port = htons(port_number);
/* Binding */
if (bind(socket_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
perror("Error on binding!");
exit(1);
}
const int thread_pool_step = 10;
listen(socket_fd, thread_pool_step);
client_length = sizeof(cli_addr);
int thread_pool_size = thread_pool_step;
pthread_t *thread_ids = malloc(thread_pool_size * sizeof(pthread_t));
if (thread_ids == NULL)
{
perror("Failed to allocate memory for thread ids");
abort();
}
memset(thread_ids, 0, thread_pool_size * sizeof(pthread_t));
int thread_index = -1;
struct sigaction a;
a.sa_handler = sigterm_handler;
a.sa_flags = 0;
sigemptyset(&a.sa_mask);
sigaction(SIGINT, &a, NULL);
sigaction(SIGQUIT, &a, NULL);
sigaction(SIGTERM, &a, NULL);
while (!do_shutdown)
{
client_socket_fd = accept(socket_fd, (struct sockaddr *)(&cli_addr), &client_length);
if (client_socket_fd == -1)
{
fprintf(stderr, "accept() failed: %s\n", strerror(errno));
break;
}
new_sock = malloc(sizeof(client_socket_fd));
*new_sock = client_socket_fd;
if (++thread_index >= thread_pool_size)
{
thread_pool_size += thread_pool_step;
thread_ids = realloc(thread_ids, thread_pool_size * sizeof(pthread_t));
if (thread_ids == NULL)
{
fprintf(stderr, "failed to realloc thread pool: %s\n", strerror(errno));
abort();
}
}
if (pthread_create(&thread_ids[thread_index++], NULL,
handle_connection, (void*) new_sock))
{
fprintf(stderr, "pthread_create() failed: %s\n", strerror(errno));
abort();
}
}
puts("Waiting for threads to finish");
while (--thread_index >= 0)
{
if (thread_ids[thread_index])
pthread_join(thread_ids[thread_index], NULL);
}
if (thread_ids != NULL)
free(thread_ids);
return 0;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
int socket_fd, port_number;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
int rc;
if (argc<2)
{
fprintf(stderr,"Incorrect arguments input\n");
exit(0);
}
port_number = 12345;
server = gethostbyname(argv[1]);
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd < 0)
{
perror("Error opening socket");
exit(1);
}
bzero((char*) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port_number);
bcopy((char*) server->h_addr,(char *)
&serv_addr.sin_addr.s_addr,sizeof(server->h_length));
if (connect(socket_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
perror("Error connecting");
exit(1);
}
enum
{
INIT_STATE,
READY_STATE
} serv_state = INIT_STATE;
#define check_serv_state(str, st) \
(strncmp(str, #st, sizeof(#st) - 1) == 0)
for (;;)
{
bzero(buffer, sizeof(buffer)/sizeof(buffer[0]));
rc = recv(socket_fd, buffer, sizeof(buffer), 0);
if (rc < 0)
{
perror("Error reading back from server");
exit(1);
}
else if (rc == 0)
{
printf("The server has been disconnected. Quitting.\n");
exit(0);
}
if (serv_state == INIT_STATE)
{
char *part = strtok(buffer, "\n");
do
{
if (check_serv_state(part, READY))
{
printf("The server is ready for the chat\n");
serv_state = READY_STATE;
}
else
printf("Server: [[[%s]]]\n", part);
}
while ((part = strtok(NULL, "\n")));
if (serv_state != READY_STATE)
continue;
}
else
printf("Server reply: %s", buffer);
bzero(buffer, sizeof(buffer)/sizeof(buffer[0]));
printf("Enter the message: ");
bzero(buffer, sizeof(buffer)/sizeof(buffer[0]));
fgets(buffer, sizeof(buffer)/sizeof(buffer[0]) - 1, stdin);
if (send(socket_fd, buffer, strlen(buffer), 0) < 0)
{
perror("Error sending message");
exit(1);
}
}
close(socket_fd);
return 0;
}
关于客户端在新建立的连接上收不到消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39770973/
我知道这个问题可能已经被问过,但我检查了所有这些,我认为我的情况有所不同(请友善)。所以我有两个数据集,第一个是测试数据集,第二个是我保存在数据框中的预测(预测值,这就是没有数据列的原因)。我想合并两
在 .loc 方法的帮助下,我根据同一数据框中另一列中的值来识别 Panda 数据框中某一列中的值。 下面给出了代码片段供您引用: var1 = output_df['Player'].loc[out
当我在 Windows 中使用 WinSCP 通过 Ubuntu 连接到 VMware 时,它提示: The server rejected SFTP connection, but it lis
我正在开发一个使用 xml web 服务的 android 应用程序。在 wi-fi 网络中连接时工作正常,但在 3G 网络中连接时失败(未找到 http 404)。 这不仅仅发生在设备中。为了进行测
我有一个XIB包含我的控件的文件,加载到 Interface Builder(Snow Leopard 上的 Xcode 4.0.2)中。 文件的所有者被设置为 someClassController
我在本地计算机上管理 MySQL 数据库,并通过运行以下程序通过 C 连接到它: #include #include #include int main(int argc, char** arg
我不知道为什么每次有人访问我网站上的页面时,都会打开一个与数据库的新连接。最终我到达了大约 300 并收到错误并且页面不再加载。我认为它应该工作的方式是,我将 maxIdle 设置为 30,这意味着
希望清理 NMEA GPS 中的 .txt 文件。我当前的代码如下。 deletes = ['$GPGGA', '$GPGSA', '$GPGSV', '$PSRF156', ] searchquer
我有一个 URL、一个用户名和一个密码。我想在 C# .Net WinForms 中建立 VPN 连接。 你能告诉我从哪里开始吗?任何第三方 API? 代码示例将受到高度赞赏... 最佳答案 您可以像
有没有更好的方法将字符串 vector 转换为字符 vector ,字符串之间的终止符为零。 因此,如果我有一个包含以下字符串的 vector "test","my","string",那么我想接收一
我正在编写一个库,它不断检查 android 设备的连接,并在设备连接、断开连接或互联网连接变慢时给出回调。 https://github.com/muddassir235/connection_ch
我的操作系统:Centos 7 + CLOUDLINUX 7.7当我尝试从服务器登录Mysql时 [root@server3 ~]# Mysql -u root -h localhost -P 330
我收到错误:Puma 发现此错误:无法打开到本地主机的 TCP 连接:9200(连接被拒绝 - 连接(2)用于“本地主机”端口 9200)(Faraday::ConnectionFailed)在我的
请给我一些解决以下错误的方法。 这是一个聊天应用....代码和错误如下:: conversations_controller.rb def create if Conversation.bet
我想将两个单元格中的数据连接到一个单元格中。我还想只组合那些具有相同 ID 的单元格。 任务 ID 名称 4355.2 参与者 4355.2 领袖 4462.1 在线 4462.1 快速 4597.1
我经常需要连接 TSQL 中的字段... 使用“+”运算符时 TSQL 强制您处理的两个问题是 Data Type Precedence和 NULL 值。 使用数据类型优先级,问题是转换错误。 1)
有没有在 iPad 或 iPhone 应用程序中使用 Facebook 连接。 这个想法是登录这个应用程序,然后能够看到我的哪些 facebook 用户也在使用该应用程序及其功能。 最佳答案 是的。
我在连接或打印字符串时遇到了一个奇怪的问题。我有一个 char * ,可以将其设置为字符串文字的几个值之一。 char *myStrLiteral = NULL; ... if(blah) myS
对于以下数据 - let $x := "Yahooooo !!!! Select one number - " let $y := 1 2 3 4 5 6 7 我想得到
我正在看 UDEMY for perl 的培训视频,但是视频不清晰,看起来有错误。 培训展示了如何使用以下示例连接 2 个字符串: #!usr/bin/perl print $str = "Hi";
我是一名优秀的程序员,十分优秀!