c - 在 C 中运行客户端和服务器套接字连接 - 使用线程

标签 c multithreading sockets

我正在尝试创建客户端和服务器的简单套接字连接。 我写了一些非常基本的东西,如下 this guide .

我正在使用client.c:

#include <stdio.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <string.h> 
#define PORT 8080 
   
int client() 
{ 
    int sock = 0, valread; 
    struct sockaddr_in serv_addr; 
    char *hello = "Hello from client"; 
    char buffer[1024] = {0}; 
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
    { 
        printf("\n Socket creation error \n"); 
        return -1; 
    } 
   
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_port = htons(PORT); 
       
    // Convert IPv4 and IPv6 addresses from text to binary form 
    if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)  
    { 
        printf("\nInvalid address/ Address not supported \n"); 
        return -1; 
    } 
   
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) 
    { 
        printf("\nConnection Failed \n"); 
        return -1; 
    } 
    send(sock , hello , strlen(hello) , 0 ); 
    printf("Hello message sent\n"); 
    valread = read( sock , buffer, 1024); 
    printf("%s\n",buffer ); 
    return 0; 
} 

和server.c:

#include <unistd.h> 
#include <stdio.h> 
#include <sys/socket.h> 
#include <stdlib.h> 
#include <netinet/in.h> 
#include <string.h> 
#define PORT 8080 

int server() 
{ 
    int server_fd, new_socket, valread; 
    struct sockaddr_in address; 
    int opt = 1; 
    int addrlen = sizeof(address); 
    char buffer[1024] = {0}; 
    char *hello = "Hello from server"; 
       
    // Creating socket file descriptor 
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) 
    { 
        perror("socket failed"); 
        exit(EXIT_FAILURE); 
    } 
       
    // Forcefully attaching socket to the port 8080 
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, 
                                                  &opt, sizeof(opt))) 
    { 
        perror("setsockopt"); 
        exit(EXIT_FAILURE); 
    } 
    address.sin_family = AF_INET; 
    address.sin_addr.s_addr = INADDR_ANY; 
    address.sin_port = htons( PORT ); 
       
    // Forcefully attaching socket to the port 8080 
    if (bind(server_fd, (struct sockaddr *)&address,  
                                 sizeof(address))<0) 
    { 
        perror("bind failed"); 
        exit(EXIT_FAILURE); 
    } 
    if (listen(server_fd, 3) < 0) 
    { 
        perror("listen"); 
        exit(EXIT_FAILURE); 
    } 
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address,  
                       (socklen_t*)&addrlen))<0) 
    { 
        perror("accept"); 
        exit(EXIT_FAILURE); 
    } 
    valread = read( new_socket , buffer, 1024); 
    printf("%s\n",buffer ); 
    send(new_socket , hello , strlen(hello) , 0 ); 
    printf("Hello message sent\n"); 
    return 0; 
} 

我想要做的一个重要更改是从单个代码文件运行客户端和服务器,其中我使用 pthread 在单个线程上运行服务器,同时在另一个线程上运行客户端。

我以前使用过pthreads,但是这次它不能正常工作。没有消息被发送,看起来服务器没有在监听。主要功能如下:

int main(){
pthread_t threads[NUM_THREADS];
int ret;
printf("In main: creating thread server\n");
ret = pthread_create(&threads[0], NULL, &server, NULL);
if (ret){
    printf("ERROR; return code from pthread_create() is %d\n", ret);
    exit(-1);
}

printf("In main: creating thread client\n");
ret = pthread_create(&threads[1], NULL, &client, NULL);
if (ret){
    printf("ERROR; return code from pthread_create() is %d\n", ret);
    exit(-1);
}
}

其中客户端服务器功能是基本功能,与前面提到的指南完全相同。 线程已创建,主函数执行没有错误,但服务器和客户端函数无法正常运行。我开始怀疑套接字连接可能无法在类似线程的配置中运行。在这件事上如果有任何帮助,我们将不胜感激。

编辑: 检查服务器文件执行后,我注意到它在 accept 函数中丢失了。更具体地说,在 server.c 文件中:

    if ((new_socket = accept(server_fd, (struct sockaddr *)&address,  
                       (socklen_t*)&addrlen))<0) 
    { 
        perror("accept"); 
        exit(EXIT_FAILURE); 
    } 

它不会越过这个函数,这意味着它确实击中了“accept”函数,并且它进入了它的内部,但它永远不会离开它。它永远不会为 new_socket 分配任何值,也不会进入 if 语句以命中 perror("accept");

谢谢

最佳答案

根据您在评论中提供的信息,与 @Andreas Wenzel、@encs 和 @IS 评论链接:

  • 您需要等待线程完成。添加一个 join 函数来阻塞主线程,同时其他线程正在运行
  • 在每个 printf() 之后使用 fflush() 以避免与缓冲相关的问题
  • 在任何客户端尝试连接之前,服务器应处于监听状态。为了确保这一点,请在主线程中设置服务器,并为accept()函数下面的所有内容创建一个pthread。

关于c - 在 C 中运行客户端和服务器套接字连接 - 使用线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63488369/

相关文章:

c# - 将记录插入到 SQL Server CE 数据库移动到另一个线程? C# Compact Framework 3.5

C# 同步对象 - 具有写入访问器的重复代码

c - 当我在 linux 下的 c 套接字中使用 read() 和 write() 时尺寸缩小

Ruby TCPSocket 读取直到自定义终止符

代码厨师 : reverse Polish Notation

c - 类型转换 - unsigned 到 signed int/char

c++ - malloc 和堆 : extra memory for storing the size and linked list information?

multithreading - 套接字服务器中每个客户端连接有新线程?

java - 读取和处理流

c++ - Eclipse C++ 包含错误 : no such file or directory