如何在c中正确使用线程和套接字? [英] how to use threading and sockets in c correctly?
问题描述
我创建了一个带有线程和套接字的简单聊天应用程序,但是我的 conn_1 只能发送消息,而 conn_2 只能接收消息.但他们应该做接收和发送.我尝试让程序在后台运行这两个函数,它们正在接收消息并将消息发送到另一个连接.有人能帮我吗?我不知道我做错了什么.
源代码:
#include #include #include #include #include #include #define PORT_CONN1 4444#define PORT_CONN2 4445字符 buf1[1024];字符 buf2[1024];int msg_1() {而(1){recv(conn_1, &buf1, 1024, 0);发送(conn_2,buf1,sizeof(buf1),0);}}int msg_2() {而(1){recv(conn_2, &buf2, 1024, 0);发送(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 = 套接字(PF_INET,SOCK_STREAM,0);sockfd_2 = 套接字(PF_INET,SOCK_STREAM,0);setockopt(sockfd_1, SOL_SOCKET, SO_REUSEADDR, &ok, sizeof(int));setockopt(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);绑定(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);绑定(sockfd_2, (struct sockaddr *)&host_addr, sizeof(struct sockaddr));听(sockfd_1, 5);听(sockfd_2, 5);而(1){pthread_t 线程1,线程2;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);关闭(conn_1);关闭(conn_2);}}
我不知道我做错了什么.
一些提示.
首先你的程序无法编译
- 在
msg_1
和msg_2
中,您使用未定义的conn_1
和conn_2
(它们是main
中的局部变量) memset
的第二个参数必须是一个 int 指定用于设置内存块的字节,你给出一个 char 数组("\0"
)msg_1
和msg_2
的签名与thread_create
不兼容
你想通过socket(s)在两个线程之间交换数据,你不需要使用两个sockets,一个就足够了,因为一个socket双向(与管道相反).
要有一个socket,你需要一个服务器和一个客户端,同一个线程不能同时存在,accept
会阻塞thread 直到客户端连接.在您的程序中,主线程 类接受,但没有要连接的客户端,因此您肯定被阻止了.
main
的结尾在 while
中的事实是相当模糊的.这也是 pthread_exit(NULL);
的情况,如果您使用该函数,它会在两个 线程 中,但不在 main
中.>
注意所使用的套接字是一个流,这意味着当你阅读它时,你不能假设你得到的字节数.这是与数据报的区别.
因此,有人需要成为您的套接字的服务器,而并行运行的其他必须成为客户端.因为 socket 将用于在 线程 之间交换数据,所以看起来很自然,一个是服务器,另一个是客户端.注意使用两个额外的线程是没有用的,因为你的 main thread 将无事可做,所以你只能有一个额外的线程 而不是两个.
为了简化,我鼓励你做第一个版本,其中 main 是服务器,唯一的附加 线程 是客户端.警告不要太早或太晚启动额外的线程,这意味着在 listen
之后但在 accept
之前.
I created a simple chat app with threading and sockets, however my conn_1 can only send messages and conn_2 only receives messages. But they should do receiving and sending. I tried that the programm runs the two functions in the background, which are receiving and sending the messages to the other connection. Can some one help me? I dont know what I did wrong.
Source code:
#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.
Some hints.
First your program cannot compile
- in
msg_1
andmsg_2
you use theconn_1
andconn_2
which are undefined (they are local variables inmain
) - the second argument of
memset
must be an int specifying the byte used to set the block of memory, you give an array of char ("\0"
) - the signature of
msg_1
andmsg_2
are not compatible withthread_create
You want to exchange data between two threads through socket(s), you do not need to use two sockets for that, only one is enough because a socket is bi directional (contrarily with the pipes).
To have a socket you need a server and a client, the same thread cannot be both of them, accept
blocks the thread until a client connects. In your program the main thread class accept but there is no client to connect, so you are definitively blocked.
The fact the end of main
is in a while
is quite obscure. This is also the case of pthread_exit(NULL);
if you use that functions this is in the two threads but not in main
.
Note the used socket is a stream, that means when you read on it you cannot suppose something about the number of bytes you get. This is the difference with the datagram.
So someone needs to be the server of your socket and someone else running in parallel must the a client. Because the socket will be used to exchange data between threads it seems natural one is the server and the other one the client. Note to use two additional threads is useless because your main thread will have nothing to do, so you can just have one additional thread rather than two.
To simplify I encourage you to do a first version where the main is the server and the only one additional thread is the client. Warning to not launch the additional thread too early nor too late, that means after the listen
but before the accept
.
这篇关于如何在c中正确使用线程和套接字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!