如何在c中正确使用线程和套接字? [英] how to use threading and sockets in c correctly?

查看:37
本文介绍了如何在c中正确使用线程和套接字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个带有线程和套接字的简单聊天应用程序,但是我的 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_1msg_2 中,您使用未定义的conn_1conn_2(它们是main 中的局部变量)
  • memset 的第二个参数必须是一个 int 指定用于设置内存块的字节,你给出一个 char 数组("\0")
  • msg_1msg_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 and msg_2 you use the conn_1 and conn_2 which are undefined (they are local variables in main)
  • 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 and msg_2 are not compatible with thread_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆