c - 如何正确使用c中的线程和套接字?
问题描述
我创建了一个带有线程和套接字的简单聊天应用程序,但是我的 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);
}
}
解决方案
我不知道我做错了什么。
一些提示。
首先你的程序无法编译
- in
msg_1
并且msg_2
您使用未定义的conn_1
andconn_2
(它们是 中的局部变量main
) - 的第二个参数
memset
必须是一个int,指定用于设置内存块的字节,您给出一个char ("\0"
)数组 - 的签名
msg_1
和msg_2
不兼容thread_create
您想通过套接字在两个线程之间交换数据,您不需要为此使用两个套接字,只需要一个就足够了,因为套接字是双向的(与管道相反)。
要拥有一个套接字,您需要一个服务器和一个客户端,同一个线程不能同时是它们两者,accept
阻塞线程直到客户端连接。在您的程序中,主线程类接受但没有要连接的客户端,因此您绝对被阻止。
结尾main
在 awhile
中的事实非常模糊。如果您使用该函数,这也是这种情况,pthread_exit(NULL);
这是在两个线程中但不在main
.
请注意,使用的套接字是一个流,这意味着当您阅读它时,您无法假设您获得的字节数。这就是与数据报的区别。
因此,需要有人成为您的套接字的服务器,而并行运行的其他人必须是客户端。因为套接字将用于在线程之间交换数据,所以很自然地一个是服务器,另一个是客户端。注意使用两个额外的线程是没有用的,因为你的主 线程将无事可做,所以你可以只拥有一个额外的线程而不是两个。
为简化起见,我鼓励您做第一个版本,其中主要是服务器,唯一的一个附加线程是客户端。警告不要太早或太晚启动附加线程listen
,这意味着在accept
.
推荐阅读
- c++ - 内存映射文件写入 C++ 在 mql4 中读取
- node.js - 将数据传递到 react-router 中的下一个屏幕
- c++ - 为什么这是“错误数量的模板参数”?
- visual-studio-code - 默认情况下如何使用预览笔记本编辑器打开 .ipyjn 文件
- powershell - 输入单个文件夹并执行 PowerShell 命令
- firebase - Firebase“CurrentUser displayName”不会随底页更新
- python - 使用梯度下降的线性回归;成本函数值有问题
- c++ - 如何以编程方式停止在 Qt 中编辑 QTreeWidget?
- java - 类之间有更好的关系吗?为什么?
- javascript - 正则表达式匹配长文本中的问题句子