#include int inc(int a) { return(++a); } int multi(int*a,int*b,int*c) { return(*c=*a**b); }

本文通过一个具体的C语言示例,深入解析了函数指针的定义与使用方法,并探讨了函数名与函数指针之间的区别。同时,还介绍了如何正确地在函数中传递和调用另一个函数。

今天做到一题面试题如下, 读到第9行的时候发现和自己理解的有出入。

个人理解函数名是函数的入口地址就是一个人指针,那为什么还要取地址再赋值给p呢?

带着疑惑百度了一番,发现网上没人发现程序中的问题,所以就记录一下,希望以后做到这题的同学不再被误解。

错误

//代码为网上复制的,存在许多问题
//运行的结果提示: 程序中有游离的‘\343’等一系列错误
#include <stdio.h>   
int inc(int a)   
{ return(++a); }   
int multi(int*a,int*b,int*c)   
{   return(*c=*a**b); }  
typedef int(FUNC1)(int in);   
typedef int(FUNC2) (int*,int*,int*);  
void show(FUNC2 fun,int arg1, int*arg2)  
{    
  FUNC1 p=&inc;   
  int temp =p(arg1);   
  fun(&temp,&arg1, arg2);   
  printf("%dn",*arg2);   
}   
main()   
{   
 int a;          
 show(multi,10,&a);    
 return 0;
}  

于是自己手打了一遍:

#include <stdio.h>

int inc(int a)
{
    return (++a);
}

int multi(int * a, int * b, int *c)
{
    return (*c = *a * *b);
}

typedef int(FUNC1)(int in);
typedef int(FUNC2)(int *,int *,int *);

void show(FUNC2 fun,int arg1,int * arg2)
{
    FUNC1 p = &inc;
    int temp = p(arg1);
    fun(&temp,&arg1,arg2);
    printf("%d\n",*arg2);
}
int main()
{
    int a;
    show(multi,10,&a);
    return 0;
}
//编译结果错误为:
//test.c: 在函数 ‘show’ 中:
//test.c:26: 错误:函数 ‘p’ 像变量一样被初始化

分析:

FUNC1 p = &inc;
左: 定义一个形参为int型,返回值为int型的函数p(p为函数的入口地址)。
右: 将函数inc()的入口地址 取 地址;
左右明显是不同的数据类型。

修改

//方法一:
#include <stdio.h>

int inc(int a)
{
    return (++a);
}

int multi(int * a, int * b, int *c)
{
    return (*c = *a * *b);
}

typedef int(*FUNC1)(int in);    //此时FUNC1变成了指向函数的指针
typedef int(FUNC2)(int *,int *,int *);

void show(FUNC2 fun,int arg1,int * arg2)
{
    FUNC1 p = &inc;  
//  FUNC1 p = inc;  这样写也是对的,不知道如何理解。
//  个人理解: 像int a[10]一样 ,  a和&a 是一个地址     
    int temp = p(arg1);
    fun(&temp,&arg1,arg2);
    printf("%d\n",*arg2);
}
int main()
{
    int a;
    show(multi,10,&a);
    return 0;
}
//方法二:
#include <stdio.h>

int inc(int a)
{
    return (++a);
}

int multi(int * a, int * b, int *c)
{
    return (*c = *a * *b);
}

typedef int(FUNC1)(int in);    
typedef int(FUNC2)(int *,int *,int *);

void show(FUNC2 fun,int arg1,int * arg2)
{
    FUNC1 *p = &inc;     //定义一个指针p指向一个形参为int型,返回值为int型的函数 
    int temp = p(arg1);
    fun(&temp,&arg1,arg2);
    printf("%d\n",*arg2);
}
int main()
{
    int a;
    show(multi,10,&a);
    return 0;
}

问题

//为什么在typedef int(FUNC2)(int *,int *,int *);的FUNC前加*程序也是对的
//请看到这篇文章的同学,帮我一下,谢谢。
//如下:
#include <stdio.h>

int inc(int a)
{
    return (++a);
}

int multi(int * a, int * b, int *c)
{
    return (*c = *a * *b);
}

typedef int(FUNC1)(int in);    
typedef int(*FUNC2)(int *,int *,int *);

void show(FUNC2 fun,int arg1,int * arg2)
{
    FUNC1 *p = &inc;     //定义一个指针p指向一个形参为int型,返回值为int型的函数 
    int temp = p(arg1);
    fun(&temp,&arg1,arg2);
    printf("%d\n",*arg2);
}
int main()
{
    int a;
    show(multi,10,&a);
    return 0;
}
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <sys/socket.h> #include <netinet/in.h> #include <dirent.h> #include <signal.h> #include <fcntl.h> #include <ctype.h> #include <wait.h> #include <sys/epoll.h> /**************************************************************************************************/ /* DEFINES */ #define PORT 8888 #define WEB_ROOT "./web" /**************************************************************************************************/ /**************************************************************************************************/ /* TYPES */ enum method_enum { MULTI_PROG, MULTI_THRD, MULTI_IO }; /**************************************************************************************************/ /**************************************************************************************************/ /* EXTERN_PROTOTYPES */ /**************************************************************************************************/ /**************************************************************************************************/ /* LOCAL_PROTOTYPES */ /**************************************************************************************************/ /**************************************************************************************************/ /* VARIABLES */ int method = MULTI_IO; /**************************************************************************************************/ /**************************************************************************************************/ /* LOCAL_FUNCTIONS */ static char *url_decode(const char *str); static void log_request(const char *method, const char *path, int status, const char *status_msg); static int send_response(int sock, int status, const char *status_msg, const char *content_type, const char *body, int body_len); static void *handle_request(void *arg); /**************************************************************************************************/ /**************************************************************************************************/ /* PUBLIC_FUNCTIONS */ /**************************************************************************************************/ /* * fn static char *url_decode(const char *str) * brief Parses the URL in the Post. * * param[in] input_int The URL in the Post. * * return the parsesd result */ static char *url_decode(const char *str_in) { char *output = malloc(strlen(str_in) + 1); if (!output) return NULL; char *dst = output; while (*str_in) { if (*str_in == '+') { *dst++ = ' '; str_in++; } else if (*str_in == '%' && isxdigit(str_in[1]) && isxdigit(str_in[2])) { char hex[3] = {str_in[1], str_in[2], '\0'}; *dst++ = (char)strtol(hex, NULL, 16); str_in += 3; } else { *dst++ = *str_in++; } } *dst = '\0'; return output; } static void log_request(const char *method, const char *path, int status, const char *status_msg) { printf("[%s] %s -> %d %s\n", method, path, status, status_msg); } /* * fn static void send_response(int sock, int status, const char *status_msg, const char *content_type, const char *body, int body_len) * brief Send a response to the browser. * * param[in] sock Client socket. * param[in] status Response status. * param[in] status_msg Meaning of response status. * param[in] content_type Type of body. * param[in] body Data to be send. * param[in] body_len Length of body. * * return the send result */ static int send_response(int sock, int status, const char *status_msg, const char *content_type, const char *body, int body_len) { char header[1024]; snprintf(header, sizeof(header), "HTTP/1.1 %d %s\r\n" "Content-Type: %s\r\n" "Content-Length: %d\r\n" "Connection: close\r\n\r\n", status, status_msg, content_type, body_len); size_t result = 0; result = send(sock, header, strlen(header), 0); if (result == -1) { close(sock); return -1; } if (body && body_len > 0) { send(sock, body, body_len, 0); if (result == -1) { close(sock); return -1; } } return 0; } /* * fn static void *handle_request(void *arg) * brief Handle the request from browser. * * param[in] arg Pointer of the client socket. * * return meaningless */ static void *handle_request(void *arg) { int sock = *(int *)arg; if(MULTI_IO != method){ free(arg); } char buffer[4096]; size_t bytes_read = recv(sock, buffer, sizeof(buffer) - 1, 0); if (bytes_read <= 0) { close(sock); return NULL; } buffer[bytes_read] = '\0'; char method[16], path[256]; sscanf(buffer, "%s %s", method, path); if (strcmp(method, "GET") == 0) { char filepath[512]; if (strcmp(path, "/") == 0) { strcpy(path, "/Index.html"); } sprintf(filepath, "%s%s", WEB_ROOT, path); FILE *file = fopen(filepath, "rb"); if (file) { fseek(file, 0, SEEK_END); long len = ftell(file); fseek(file, 0, SEEK_SET); char *content = malloc(len); fread(content, 1, len, file); fclose(file); const char *content_type = "text/html"; if (strstr(path, ".css")) { content_type = "text/css"; } else if (strstr(path, ".js")) { content_type = "application/json"; } else if (strstr(path, ".png")) { content_type = "image/png"; } else if (strstr(path, ".jpg")) { content_type = "image/jpeg"; } send_response(sock, 200, "OK", content_type, content, len); free(content); log_request(method, path, 200, "OK"); } else { const char *not_found = "<h1>404 Not Found</h1>"; send_response(sock, 404, "Not Found", "text/html", not_found, strlen(not_found)); log_request(method, path, 404, "Not Found"); } } else if (strcmp(method, "POST") == 0) { char *content_length_ptr = strstr(buffer, "Content-Length: "); int content_length = 0; if (content_length_ptr) { sscanf(content_length_ptr + 16, "%d", &content_length); } if (content_length <= 0) { const char *bad_request = "<h1>400 Bad Request: Missing Content-Length</h1>"; send_response(sock, 400, "Bad Request", "text/html", bad_request, strlen(bad_request)); log_request(method, path, 400, "Bad Request"); close(sock); return NULL; } char *post_data = malloc(content_length + 1); if (!post_data) { const char *server_error = "<h1>500 Internal Server Error</h1>"; send_response(sock, 500, "Server Error", "text/html", server_error, strlen(server_error)); log_request(method, path, 500, "Server Error"); close(sock); return NULL; } char *body_start = strstr(buffer, "\r\n\r\n"); if (body_start) { body_start += 4; memcpy(post_data, body_start, content_length); } else { const char *bad_request = "<h1>400 Bad Request: Bad Message Format</h1>"; send_response(sock, 400, "Bad Request", "text/html", bad_request, strlen(bad_request)); log_request(method, path, 400, "Bad Request"); close(sock); return NULL; } post_data[content_length] = '\0'; /* post_data : name=z111&email=125253455%40qq.com&message=dasdsasd */ if (strcmp(path, "/data/contact.json") == 0) { char name[128] = {0}; char email[128] = {0}; char message[512] = {0}; char *token = strtok(post_data, "&"); while (token != NULL) { char *eq = strchr(token, '='); if (eq) { *eq = '\0'; char *key = token; char *value = url_decode(eq + 1); if (strcmp(key, "name") == 0) { strncpy(name, value, sizeof(name) - 1); } else if (strcmp(key, "email") == 0) { strncpy(email, value, sizeof(email) - 1); } else if (strcmp(key, "message") == 0) { strncpy(message, value, sizeof(message) - 1); } free(value); } token = strtok(NULL, "&"); } char response[1024]; snprintf(response, sizeof(response), "{" "\"callback\": \"Message received successfully\"," "\"details\": {" "\"name\": %s," "\"email\": %s," "\"message\": %s" "}" "}", name, email, message); send_response(sock, 200, "OK", "application/json", response, strlen(response)); log_request(method, path, 200, "OK"); } else { const char *not_implemented = "<h1>501 Not Implemented</h1>"; send_response(sock, 501, "Not Implemented", "text/html", not_implemented, strlen(not_implemented)); log_request(method, path, 501, "Not Implemented"); close(sock); return NULL; } free(post_data); } else { const char *not_implemented = "<h1>501 Not Implemented</h1>"; send_response(sock, 501, "Not Implemented", "text/html", not_implemented, strlen(not_implemented)); log_request(method, path, 501, "Not Implemented"); close(sock); return NULL; } close(sock); return NULL; } int main() { /* 当client先终止连接,server向socket中写文件时会触发SIGPIPE信号导致程序退出 */ /* 此处忽略SIGPIPE信号,在send_response中做处理 */ signal(SIGPIPE, SIG_IGN); int server_fd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addr = { .sin_family = AF_INET, .sin_port = htons(PORT), .sin_addr.s_addr = htonl(INADDR_ANY)}; bind(server_fd, (struct sockaddr *)&addr, sizeof(addr)); listen(server_fd, 10); printf("Web server running on port %d\n", PORT); if (MULTI_IO == method) { int epoll_fd = epoll_create1(0); struct epoll_event ev, events[100]; ev.events = EPOLLIN; ev.data.fd = server_fd; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev); while (1) { int n = epoll_wait(epoll_fd, events, 100, -1); for (int i = 0; i < n; i++) { if (events[i].data.fd == server_fd) { int client_fd = accept(server_fd, NULL, NULL); ev.events = EPOLLIN | EPOLLET; ev.data.fd = client_fd; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev); } else { handle_request(&events[i].data.fd); epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, NULL); close(events[i].data.fd); } } } epoll_ctl(epoll_fd, EPOLL_CTL_DEL, server_fd, NULL); }else{ while (1) { int client_fd = accept(server_fd, NULL, NULL); if (client_fd < 0) { perror("accept failed"); continue; } int *sock_ptr = malloc(sizeof(int)); if (!sock_ptr) { close(client_fd); continue; } *sock_ptr = client_fd; if (MULTI_PROG == method) { pid_t pid = fork(); if (pid == 0) { close(server_fd); handle_request(sock_ptr); exit(0); } else { close(client_fd); waitpid(-1, NULL, WNOHANG); } } else if (MULTI_THRD == method) { pthread_t tid; pthread_create(&tid, NULL, handle_request, sock_ptr); pthread_detach(tid); } } } close(server_fd); return 0; } 如何优化代码使得其具有高并发性
08-02
/* *\file server.c *\brief This code is a function for socket tcp server. *\author Chen Xinyi <chenxinyi1@tp-link.com.hk> *\version 1.0.0 *\date 6/8/2025 *\history \arg 1.0.0 6/8/2025, chenxinyi, Create file. */ /**************************************************************************************************/ /*****************************************INCLUDE_FILES********************************************/ /**************************************************************************************************/ #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <malloc.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <stdarg.h> #include <fcntl.h> #include <fcntl.h> /* 涉及到多进程操作时加入如下语句: */ #include <sys/wait.h> #include <sys/ipc.h> #include <sys/shm.h> #include <signal.h> /* 涉及到多线程操作时加入如下语句: */ #include <pthread.h> #include <sys/poll.h> /**************************************************************************************************/ /********************************************DEFINES***********************************************/ /**************************************************************************************************/ #define PORT 80 #define BUFFER_SIZE 1024 /**************************************************************************************************/ /********************************************FUNCTION**********************************************/ /**************************************************************************************************/ /* void send_error(int client_fd, int status_num, const char* status_msg, const char* edition) { char response[1024]; // snprintf 将格式化的数据写入指定的字符串缓冲区,若字符串长度超了,输出被截断,并在最后添加空字符 int length = snprintf(response, sizeof(response), "%s %s %d \r\n" "server: %d\r\n" "Content-Type: image/svg+xml\r\n" "<html>\r\n" "<head>\r\n" "<title>error page</title>\n" "</head>\n" "<body>\r\n" "<h1>%d</h1>\r\n" "<%s>\r\n" "</body>\r\n" "</html>\r\n", edition, status_msg, status_num, client_fd, status_num, status_msg); send(client_fd, response, length, 0); } */ /**************************************************************************************************/ /********************************************FUNCTION**********************************************/ /**************************************************************************************************/ // 文件类型映射 const char* get_mime_type(const char *path) { /* 用于在字符串中查找某个字符最后一次出现的位置, 返回一个指向该字符的指针 */ const char *ext = strrchr(path, '.'); if (!ext) return "text/plain"; if (strcmp(ext, ".html") == 0) return "text/html"; if (strcmp(ext, ".css") == 0) return "text/css"; if (strcmp(ext, ".js") == 0) return "application/javascript"; if (strcmp(ext, ".jpg") == 0 || strcmp(ext, ".jpeg") == 0) return "image/jpeg"; if (strcmp(ext, ".png") == 0) return "image/png"; return "application/octet-stream"; } /**************************************************************************************************/ /********************************************FUNCTION**********************************************/ /**************************************************************************************************/ /* 用来从server获取数据,因此需要解析GET请求的具体资源类型 */ void handle_get(int client_fd, char* path) { char uri[BUFFER_SIZE], http_version[BUFFER_SIZE]; sscanf(path, "%s %s", uri, http_version); // 构建文件路径 char full_path[512]; if (strcmp(uri, "/") == 0) { snprintf(full_path, sizeof(full_path), "%s/Index.html", "./web"); } else { snprintf(full_path, sizeof(full_path), "%s%s", "./web", uri); } /* 当请求是GET,需要读取文件并且返回,调用open等与文件系统交互,同时处理404错误和目录遍历问题 */ /* 1.打开文件 */ FILE* file = fopen(full_path, "rb"); if (!file) { printf("无法打开文件: %s (%s)\n", full_path, strerror(errno)); char *response_er = "HTTP/1.1 500 Internal Server Error\r\n" "\r\n"; send(client_fd, response_er, strlen(response_er), 0); return; } // 获取文件大小 fseek(file, 0, SEEK_END); long size = ftell(file); fseek(file, 0, SEEK_SET); // 发送HTTP头 char header[BUFFER_SIZE]; snprintf(header, sizeof(header), "HTTP/1.0 200 OK\r\nContent-Type: %s\r\nContent-Length: %ld\r\nConnection: close\r\n\r\n", get_mime_type(full_path), size); send(client_fd, header, strlen(header), 0); // 发送文件内容 char buffer[BUFFER_SIZE]; size_t bytes_read; while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0) { send(client_fd, buffer, bytes_read, 0); } fclose(file); } /**************************************************************************************************/ /********************************************FUNCTION**********************************************/ /**************************************************************************************************/ char *get_header_value(char *header, char *key) { char *key_pos = strstr(header, key); if (key_pos == NULL) { return NULL; } /* strchr搜索在另字符串中第一次出现,默认false,如果为true则返回search参数第一次出现之前的字符串部分 */ char *value_pos = strchr(key_pos, ':'); if(value_pos == NULL) { return NULL; } value_pos++; while (*value_pos == ' ') { value_pos++; } char *end_pos = strstr(value_pos, "\r\n"); if(end_pos == NULL) { return NULL; } *end_pos = '\0'; return value_pos; } /**************************************************************************************************/ /********************************************FUNCTION**********************************************/ /**************************************************************************************************/ /* 修改server数据,数据放在request里: * post产生两个TCP包,浏览器先发送header,100后,浏览器再发送打压,返回200 */ void handle_post(int client_fd, char* path) { char *header = {0}; char *body = {0}; /* 寻找有无Length头 */ header = strstr(path, "Content-Length"); if (header == NULL) { return; } /* atoi把参数str所指向的字符串转换为一个整数 */ int content_length = atoi(get_header_value(header, "Content-Length")); body = strstr(path, "\r\n\r\n")+4; if (body == NULL) { return; } printf("POST request body: %.*s\n", content_length, body); char *response = "HTTP/1.1 200 OK\r\n" "Content-Type: Text/plain\r\n" "\r\n" "success!"; send(client_fd, response, strlen(response), 0); } /**************************************************************************************************/ /********************************************FUNCTION**********************************************/ /**************************************************************************************************/ /* 解读http报文 */ void handle_http_request(int client_fd) { char request[BUFFER_SIZE] = {0}; /* 1.读取浏览器请求*/ //read(client_fd, request, BUFFER_SIZE-1); while (1) { ssize_t bytes_read = recv(client_fd, request, BUFFER_SIZE - 1, 0); if (bytes_read <= 0) { if (bytes_read == 0) { //printf("客户端关闭了连接\n"); } else { //perror("接收请求失败"); } usleep(10000); continue; } request[bytes_read] = '\0'; // 确保字符串结束 printf("------------------ 收到请求 ------------------%s\n",request); /* 2.提取请求信息(方法、路径) */ /* strtok将字符串分割,并修改传入的字符串将分隔符替为\0, 后续调用时,传NULL,表示继续分割同一个字符串 */ char* method = strtok(request, " "); char* path = strtok(NULL, ""); if (strcmp(method, "GET") == 0) { handle_get(client_fd, path); } else if (strcmp(method, "POST") == 0) { handle_post(client_fd, path); } else { char *response = "HTTP/1.1 405 Method Not Allowed\r\n" "Content-Length: 0\r\n" "\r\n"; send(client_fd, response, strlen(response), 0); } usleep(100000); } close(client_fd); return; } /**************************************************************************************************/ /********************************************FUNCTION**********************************************/ /**************************************************************************************************/ void *pthread_handle(void *args) { int new_client_fd = *((int *)args); free(args); handle_http_request(new_client_fd); return NULL; } /**************************************************************************************************/ /********************************************FUNCTION**********************************************/ /**************************************************************************************************/ /* 线程处理函数 */ int sock_pthread(int client_fd, socklen_t clnt_addr_size, int server_fd, struct sockaddr_in client_addr, int ret) { int *new_client_fd = malloc(sizeof(int)); while (1) { /* 接受客户端的请求,新建一个套接字 */ *new_client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &clnt_addr_size); if (*new_client_fd < 0) { perror("accept failed"); close(server_fd); exit(-1); } printf("sock"); pthread_t tid; pthread_create(&tid, NULL, pthread_handle, new_client_fd); pthread_detach(tid); usleep(100000); } close(client_fd); close(server_fd); return 0; } /**************************************************************************************************/ /********************************************FUNCTION**********************************************/ /**************************************************************************************************/ /* 进程处理函数 */ int sock_process(int client_fd, socklen_t clnt_addr_size, int server_fd, struct sockaddr_in client_addr, int ret) { } /**************************************************************************************************/ /********************************************FUNCTION**********************************************/ /**************************************************************************************************/ int main() { char *method = malloc(sizeof(char)); printf("Please enter your processing method\nA.multi-thread\nB.multi-process\nC.IOmulti-plex:"); scanf("%31s",method); /* server_fd就是用于监听的,client_fd采用来进行实际的数据传输 */ //int client_fd; struct sockaddr_in client_addr = {0}; socklen_t clnt_addr_size = sizeof(client_addr); /* 1.创建socket文件描述符:创建套接字成功时返回一个非负整数 */ int server_fd; if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } /* 2.配置服务器地址 */ struct sockaddr_in serv_addr = {0}; memset(&serv_addr, 0, sizeof(serv_addr)); /* 使用IPV4地址 */ serv_addr.sin_family = AF_INET; /* 设置IP,监听本地所有网口,仅服务端可用INADDR_ANY */ serv_addr.sin_addr.s_addr = INADDR_ANY; /* 端口!需要转化为网络字节序再赋给socket */ serv_addr.sin_port = htons(PORT); /* 添加端口复用: 允许不同的进程或线程在相同的网络端口上同时进行监听和通信 */ // int opt = SO_REUSEADDR; /* 套接字选项,允许重新绑定已经在使用的地址和端口 * 允许在关闭套接字之后重新绑定使用相同地址和端口的套接字 * 因此,程序重启后能 快速监听之前使用的地址和端口 */ // setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)); /* 3.绑定server_fd到端口,文件描述符绑定到指定地址和端口 */ /* bind(socket描述字,要绑定给描述字的协议地址,对应地址长度)函数把一个地址组中特定地址赋给socket */ /* 绑定成功之后,如果客户端试图连接指定地址和端口建立TCP连接,系统就会转给server_fd这个文件处理 */ int ret = bind(server_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); if (ret < 0) { perror("bind failed"); exit(EXIT_FAILURE); } /* 4.进入监听状态 如果客户端用connct()发出请求,服务器就会监听到 */ /* int listen(int sockfd, int backlog) 监听的socket描述字,相应socket可以排队的最大连接个数 */ /* 监听server_fd,就是鉴定这个地址和端口 */ if (listen(server_fd, 3) < 0) { perror("listen failed"); exit(EXIT_FAILURE); } printf("TCP服务器已启动, 监听端口: %d\n", PORT); if (strcmp(method,"A") == 0) { sock_pthread(server_fd, clnt_addr_size, server_fd, client_addr, ret); return 0; } else if (strcmp(method,"B") == 0) { sock_process(server_fd); return 0; } /*else if (strcmp(method,"C") == 0) { sock_IO(server_fd); return 0; }*/ else { printf("Not ideal input, please re-enter!"); return 0; } }这个代码是阻塞还是非阻塞
08-11
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值