当前位置: 技术问答>linux和unix
菜鸟求救:多线程 多socket
来源: 互联网 发布时间:2017-02-19
本文导语: 大家好,看了一份源代码,就是mjpeg-streamer,用来做视频监控的,B/S架构。 服务器端开启10个线程,每个线程开了50个socket监听,每个socket都用select来处理请求,对于已accept的请求,再启动一个新线程来发送数据。 ...
大家好,看了一份源代码,就是mjpeg-streamer,用来做视频监控的,B/S架构。
服务器端开启10个线程,每个线程开了50个socket监听,每个socket都用select来处理请求,对于已accept的请求,再启动一个新线程来发送数据。
小弟对网络编程还不是很熟悉,请问这样可行么?还是我对代码理解有误
代码大致如下(注释部分是我自己写的),求救啊:
服务器端开启10个线程,每个线程开了50个socket监听,每个socket都用select来处理请求,对于已accept的请求,再启动一个新线程来发送数据。
小弟对网络编程还不是很熟悉,请问这样可行么?还是我对代码理解有误
代码大致如下(注释部分是我自己写的),求救啊:
int output_run(int id)
{
/* create thread and pass context to thread function */
pthread_create(&(servers[id].threadID), NULL, server_thread, &(servers[id]));//参数为servers[id]
pthread_detach(servers[id].threadID);
return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////分割线
/******************************************************************************
Description.: Open a TCP socket and wait for clients to connect. If clients
connect, start a new thread for each accepted connection.
Input Value.: arg is a pointer to the globals struct
Return Value: always NULL, will only return on exit
******************************************************************************/
void *server_thread( void *arg ) {
int on;
pthread_t client;
struct addrinfo *aip, *aip2; //IP地址,端口等
struct addrinfo hints;
struct sockaddr_storage client_addr;
socklen_t addr_len = sizeof(struct sockaddr_storage);
fd_set selectfds;
int max_fds = 0;
char name[NI_MAXHOST];
int err;
int i;
context *pcontext = arg;
pglobal = pcontext->pglobal;
/* set cleanup handler to cleanup ressources */
pthread_cleanup_push(server_cleanup, pcontext);
bzero(&hints, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;//使用tcp协议
snprintf(name, sizeof(name), "%d", ntohs(pcontext->conf.port));
if((err = getaddrinfo(NULL, name, &hints, &aip)) != 0) {
perror(gai_strerror(err));
exit(EXIT_FAILURE);
}
for(i = 0; i sd[i] = -1;
/* open sockets for server (1 socket / address family) */
i = 0;
for(aip2 = aip; aip2 != NULL; aip2 = aip2->ai_next)
{
//打开设备符
if((pcontext->sd[i] = socket(aip2->ai_family, aip2->ai_socktype, 0)) sd[i], SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) ai_family == AF_INET6 && setsockopt(pcontext->sd[i], IPPROTO_IPV6, IPV6_V6ONLY,
(const void *)&on , sizeof(on)) sd[i], aip2->ai_addr, aip2->ai_addrlen) sd[i] = -1;
continue;
}
//监听
if(listen(pcontext->sd[i], 10) sd[i] = -1;
} else {
i++;
if(i >= MAX_SD_LEN) {
OPRINT("%s(): maximum number of server sockets exceeded", __FUNCTION__);
i--;
break;
}
}
}
pcontext->sd_len = i;
//htons字节顺序转换函数
if(pcontext->sd_len conf.port));
closelog();
exit(EXIT_FAILURE);
}
/* create a child for every client that connects */
while ( !pglobal->stop ) {
//int *pfd = (int *)malloc(sizeof(int));
cfd *pcfd = malloc(sizeof(cfd));
if (pcfd == NULL) {
fprintf(stderr, "failed to allocate (a very small amount of) memoryn");
exit(EXIT_FAILURE);
}
DBG("waiting for clients to connectn");
do {
FD_ZERO(&selectfds);
for(i = 0; i sd[i] != -1) {
FD_SET(pcontext->sd[i], &selectfds);
if(pcontext->sd[i] > max_fds)
max_fds = pcontext->sd[i];
}
}
//select管理设备,防止阻塞
err = select(max_fds + 1, &selectfds, NULL, NULL, NULL);
if (err fd = accept(pcontext->sd[i], (struct sockaddr *)&client_addr, &addr_len);//accept连接,返回一个新的
//socket描述符,并传递到下面的pthread_create(&client, NULL, &client_thread, pcfd)中,供传递使用
//也即send的参数中使用的socket描述符
pcfd->pc = pcontext;
/* start new thread that will handle this TCP connected client */
DBG("create thread to handle client that just established a connectionn");
if(getnameinfo((struct sockaddr *)&client_addr, addr_len, name, sizeof(name), NULL, 0, NI_NUMERICHOST) == 0) {
syslog(LOG_INFO, "serving client: %sn", name);
}
//新建一个新的线程
if( pthread_create(&client, NULL, &client_thread, pcfd) != 0 ) {
DBG("could not launch another client threadn");
close(pcfd->fd);
free(pcfd);
continue;
}
pthread_detach(client);
}
}
}
DBG("leaving server thread, calling cleanup function nown");
pthread_cleanup_pop(1);
return NULL;
}
|
嵌入式方面的网络开发一般写的都比较次,个人感觉.
这代码很明显的惊群现象, 看它说arg是全局变量, 每个线程都用同一个域名做bind,还用了reuseaddr,太恶心了。
应该一个线程做监听,然后每个线程select一个管道,做异步的连接分发。
这代码很明显的惊群现象, 看它说arg是全局变量, 每个线程都用同一个域名做bind,还用了reuseaddr,太恶心了。
应该一个线程做监听,然后每个线程select一个管道,做异步的连接分发。