網路程式設計——用執行緒實現可供多客戶端訪問的伺服器
阿新 • • 發佈:2019-01-06
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <string.h> #include <unistd.h> #include <pthread.h> #define PORT 9997 void *handl_client(void *v) { int client_socket = (long)v; char buf[1024] = {"asdsadsadsadsa"}; while (1) { int ret = read(client_socket, buf, sizeof(buf)-1); if (-1 == ret) { perror ("read error"); } if (0 == ret) { printf ("客戶端退出\n"); break; } buf[ret] = '\0'; printf ("收到客戶端的資料:%s\n", buf); int i; for (i = 0; i < ret - 1; i++) { buf[i] += 'A' - 'a'; } write(client_socket, buf, ret); } } // 監聽套接字 int init() { int listen_socket = socket(AF_INET, SOCK_STREAM, 0); if(-1 == listen_socket) { perror("建立套接字失敗"); return -1; } struct sockaddr_in addr; memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; /* Internet地址族 */ addr.sin_port = htons(PORT); /* 埠號 */ addr.sin_addr.s_addr = htonl(INADDR_ANY); /* IP地址, 繫結本地的所有ip地址*/ // 2、繫結本地的 ip 地址和埠 // 第一個引數:需要繫結的套接字 // 第二個引數:是要繫結的ip和埠 // 第三個引數:第二個引數所佔的位元組數 int ret = bind(listen_socket, (const struct sockaddr *)&addr, sizeof(addr)); if(-1 == ret) { perror("繫結失敗"); return -1; } // 3、監聽套接字 ret = listen(listen_socket, 5); if(-1 == ret) { perror("監聽失敗"); return -1; } return listen_socket; } // 通訊套接字 int myAccept(int listen_socket) { struct sockaddr_in client_addr; socklen_t len = sizeof(client_addr); int client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, &len); if (-1 == client_socket) { perror("accept 失敗"); return -1; } printf ("客戶端的 ip = %s, 埠 = %d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); return client_socket; } // 主函式 int main(int argc, char **argv) { int listen_socket = init(); if(-1 == listen_socket) { perror("建立套接字失敗"); return -1; } while(1) { long client_socket = myAccept(listen_socket); if (-1 == client_socket) { continue; } // 開闢執行緒為客戶端服務 pthread_t thread; pthread_create(&thread, NULL, handl_client, (long *)client_socket); pthread_detach(thread); } close(listen_socket); return 0; }