c - 如何正确使用c中的线程和套接字?

标签 c multithreading sockets networking

我创建了一个带有线程和套接字的简单聊天应用程序,但是我的 conn_1 只能发送消息,而 conn_2 只能接收消息。但他们应该做接收和发送。我尝试让程序在后台运行这两个函数,它们正在接收消息并将消息发送到另一个连接。有人能帮我吗?我不知道我做错了什么。

源代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>

#define PORT_CONN1 4444
#define PORT_CONN2 4445

char buf1[1024];
char buf2[1024];

int msg_1() {
  while(1) {
    recv(conn_1, &buf1, 1024, 0);
    send(conn_2, buf1, sizeof(buf1), 0);
  }
}

int msg_2() {
  while(1) {
    recv(conn_2, &buf2, 1024, 0);
    send(conn_1, buf2, sizeof(buf2), 0);
  }
}

int main() {
  int sockfd_1, sockfd_2, conn_1, conn_2;
  struct sockaddr_in host_addr, client_addr;
  socklen_t sin_size;
  int recv_length=1, ok=1;

  sockfd_1 = socket(PF_INET, SOCK_STREAM, 0);
  sockfd_2 = socket(PF_INET, SOCK_STREAM, 0);
  setsockopt(sockfd_1, SOL_SOCKET, SO_REUSEADDR, &ok, sizeof(int));
  setsockopt(sockfd_2, SOL_SOCKET, SO_REUSEADDR, &ok, sizeof(int));

  host_addr.sin_family = AF_INET;
  host_addr.sin_port = htons(PORT_CONN1);
  host_addr.sin_addr.s_addr = 0;
  memset(&(host_addr.sin_zero), "\0", 8);

  bind(sockfd_1, (struct sockaddr *)&host_addr, sizeof(struct sockaddr));

  host_addr.sin_family = AF_INET;
  host_addr.sin_port = htons(PORT_CONN2);
  host_addr.sin_addr.s_addr = 0;
  memset(&(host_addr.sin_zero), "\0", 8);

  bind(sockfd_2, (struct sockaddr *)&host_addr, sizeof(struct sockaddr));

  listen(sockfd_1, 5);
  listen(sockfd_2, 5);

  while(1) {
    pthread_t thread1, thread2;
    sin_size = sizeof(struct sockaddr_in);
    conn_1 = accept(sockfd_1, (struct sockaddr *)&client_addr, &sin_size);
    conn_2 = accept(sockfd_2, (struct sockaddr *)&client_addr, &sin_size);

    pthread_create(&thread1, NULL, msg_1, NULL);
    pthread_create(&thread2, NULL, msg_2, NULL);
    pthread_exit(NULL);

    close(conn_1);
    close(conn_2);
  }
}

最佳答案

I dont know what I did wrong.



一些提示。

首先你的程序无法编译
  • msg_1msg_2您使用 conn_1conn_2未定义的(它们是 main 中的局部变量)
  • memset 的第二个参数必须是一个 int,指定用于设置内存块的字节,你给一个 char 数组("\0")
  • msg_1的签名和 msg_2thread_create 不兼容

  • 您想通过套接字在两个线程之间交换数据,您不需要为此使用两个套接字,只需要一个就足够了,因为套接字是双向的(与管道相反)。

    要拥有一个套接字,您需要一个服务器和一个客户端,同一线程不能同时是它们,accept阻塞线程直到客户端连接。在您的程序中,主线程类接受但没有要连接的客户端,因此您绝对被阻止。

    事实结束main位于 while是相当晦涩难懂的。 pthread_exit(NULL); 的情况也是如此。如果你使用那个函数,这是在两个线程中,而不是在 main 中。 .

    请注意,使用的套接字是一个流,这意味着当您阅读它时,您无法假设您获得的字节数。这就是与数据报的区别。

    因此,需要有人成为您的套接字的服务器,而并行运行的其他人必须是客户端。因为套接字将用于在线程之间交换数据,所以很自然地一个是服务器,另一个是客户端。注意使用两个额外的线程是没有用的,因为您的主线程将无事可做,因此您可以只拥有一个额外的线程而不是两个。

    为简化起见,我鼓励您做第一个版本,其中主要是服务器,唯一的一个附加线程是客户端。警告不要太早或太晚启动附加线程,这意味着在 listen 之后但在 accept 之前.

    关于c - 如何正确使用c中的线程和套接字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61364667/

    相关文章:

    c - 通过有效负载以外的方法在 Linux UDP 套接字之间交换任意数据

    c - 构建库时遇到问题

    c# - 遇到意外的联锁行为?

    java - 我无法从 AsyncTask 获得结果?

    javascript - Node.js dgram 绑定(bind)在 udp6 和 udp4 上抛出 EADDRINUSE

    c - Linux内核与多线程用户应用同步问题

    c - 如何在 C 中创建静态 volatile 结构数组?

    python - 将多个文件从一台主机传输到另一台主机

    linux - 为什么我程序中的这个线程会挨饿?

    c - MS-DOS 套接字库(C 语言)