多執行緒解決socket併發問題
阿新 • • 發佈:2019-01-27
概念
- 這篇部落格我們利用多執行緒解決伺服器併發問題
- 程序是資源分配最小的單位,執行緒是CPU排程的最小單位
- 多程序與多執行緒比較(下圖取自網路,原作者不詳)
對比維度 |
多程序 |
多執行緒 |
總結 |
資料共享、同步 |
資料共享複雜,需要用IPC;資料是分開的,同步簡單 |
因為共享程序資料,資料共享簡單,但也是因為這個原因導致同步複雜 |
各有優勢 |
記憶體、CPU |
佔用記憶體多,切換複雜,CPU利用率低 |
佔用記憶體少,切換簡單,CPU利用率高 |
執行緒佔優 |
建立銷燬、切換 |
建立銷燬、切換複雜,速度慢 |
建立銷燬、切換簡單,速度很快 |
執行緒佔優 |
程式設計、除錯 |
程式設計簡單,除錯簡單 |
程式設計複雜,除錯複雜 |
程序佔優 |
可靠性 |
程序間不會互相影響 |
一個執行緒掛掉將導致整個程序掛掉 |
程序佔優 |
分散式 |
適應於多核、多機分散式;如果一臺機器不夠,擴充套件到多臺機器比較簡單 |
適應於多核分散式 |
程序佔優 |
程式碼實現
- 伺服器端利用多執行緒程式設計
- 注意編譯的時候加上-lpthread ,否則會出現如下編譯錯誤
undefined reference to `pthread_create’
collect2: ld 返回 1
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void *thread_worker(void *arg);
int *p;
int main(int argc, char **argv)
{
int socket_fd, connect_fd = -1 ;
struct sockaddr_in serv_addr;
pthread_t tid;
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(socket_fd < 0 )
{
printf("create socket failure: %s\n", strerror(errno));
return -1;
}
printf("socket create fd[%d]\n", socket_fd);
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(9998);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if( bind(socket_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0 )
{
printf("create socket failure: %s\n", strerror(errno));
return -2;
}
printf("socket bind ok\n", socket_fd);
listen(socket_fd, 13);
printf("listen fd ok\n", socket_fd);
while(1)
{
printf("waiting for client's connection......\n", socket_fd);
connect_fd = accept(socket_fd, NULL, NULL);
p=&connect_fd;
if(connect_fd < 0)
{
printf("accept new socket failure: %s\n", strerror(errno));
return -2;
}
printf("accept ok, return connect_fd: [%d]\n", connect_fd);
pthread_create (&tid, NULL,thread_worker, (void *)p);
}
close(socket_fd);
}
void *thread_worker(void *arg)
{
char buf[1024];
int cli_fd =*p;
memset(buf, 0, sizeof(buf));
while(1){
read(cli_fd, buf, sizeof(buf));
printf("read '%s' from client\n", buf);
printf("send data to client:");
fgets(buf,sizeof(buf),stdin);
write(cli_fd, buf, strlen(buf));
sleep(1);
}
close(cli_fd);
return NULL;
}