我正在实现一个迷你youtube类型的套接字接口。在线程化main_server中从我的子服务器接收数据时会出现问题,这可以轻松处理多个子服务器。如果我在main中创建线程后通过pthread_join加入线程,则线程调用成功并且从子服务器接收数据,但这在技术上破坏了创建多线程子服务器环境的全部意义。如果我没有加入该主题,那就是错误:
Alis-MacBook-Pro:Desktop aliabbasjaffri$ gcc main_server.c -w -lpthread -o s
Alis-MacBook-Pro:Desktop aliabbasjaffri$ ./s
bind = 0 SFD: 3
Thread Created!!!
SFD: 3 Inside thread function!
recvfrom(): Bad file descriptor
ERROR RECEIVING STUFF!!!!!!!!!
Received stuff:
SubServerNum: -48
Address:
Bus error: 10
当我通过pthread_join加入线程时,执行成功并且从子服务器成功接收数据。这就是终端上出现的内容。
Alis-MacBook-Pro:Desktop aliabbasjaffri$ gcc main_server.c -w -lpthread -o s
Alis-MacBook-Pro:Desktop aliabbasjaffri$ ./s
bind = 0 SFD: 3
Thread Created!!!
SFD: 3 Inside thread function!
Received stuff: 1,0.0.0.0,8888,hello.mp4,10.0
SubServerNum: 1
Address: 0.0.0.0
Port: 8888
Video Name: hello.mp4
Video Size: 10.000000
Received stuff: 1,0.0.0.0,8888,world.mp4,20.0
SubServerNum: 1
Address: 0.0.0.0
Port: 8888
Video Name: world.mp4
Video Size: 20.000000
Received stuff: end
Exiting the thread!
我的主服务器代码如下。
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
#include <fcntl.h>
//////////////////////////////////////////////~~GLOBAL DECLARATIONS~~///////////////////////////
const int numberOfThreads = 1; //Number of threads to get data from subservers!
const int sizeOfVideosStruct = 6;
int PORT = 8889; //port number
struct sockaddr_in server , client;
socklen_t len = sizeof( client );
struct videosList
{
int serverNumber;
char address[30];
int port;
char movieName[50];
int movieSize;
};
struct videosList videos[ sizeOfVideosStruct ]; //movies from subservers
//////////////////////////////////////////////////////////////////////////////////////////////////
void subserverReplyParserAndEntryManager( char line[] )
{
int subServerNumber = 0 , i = 0 , j = 0;
int port = 0;
float size = 0;
char address[20] = "" , RPort[5] = "" , videoName[40] = "" , RSize[6] = "";
subServerNumber = line[0];
subServerNumber -= 48;
printf("SubServerNum: %d\n", subServerNumber );
for( i = 2; ; )
{
if( line[i] == ',' )
{
break;
}
address[j++] = line[i++];
}
printf("Address: %s\n", address );
i++;
j = 0;
for( ; ; )
{
if( line[i] == ',' )
{
break;
}
RPort[j++] = line[i++];
}
port = atoi(RPort);
printf("Port: %d\n", port );
i++;
j = 0;
for( ; ; )
{
if( line[i] == ',' )
{
break;
}
videoName[j++] = line[i++];
}
printf("Video Name: %s\n", videoName );
i++;
j = 0;
for( ; ; )
{
if( line[i] == '\0' )
{
break;
}
RSize[j++] = line[i++];
}
size = atoi(RSize);
printf("Video Size: %f\n\n\n", size );
}
void * subserverThreadFunction( void * threadArgument )
{
char data[1000];
int sfd = ( int ) threadArgument;
printf("SFD: %d Inside thread function!\n" , sfd);
while( strcmp( data , "end" ) != 0 )
{
if( recvfrom( sfd , data , 1000 , 0 , (struct sockaddr *)&client , &len ) == -1 )
{
perror("recvfrom()");
printf("ERROR RECEIVING STUFF!!!!!!!!!");
}
printf("\nReceived stuff: %s\n" , data);
if( strcmp( data , "end" ) == 0 )
{
break;
}
subserverReplyParserAndEntryManager( data );
}
printf("Exiting the thread!");
pthread_exit(NULL);
}
void sendDataToClient()
{
}
int main()
{
pthread_t thread;
char buffer1[1024] = "";
int num = 0 , rc = 0;
int sfd = socket( AF_INET , SOCK_DGRAM , 0);
bzero( &server , sizeof(server) );
server.sin_family = AF_INET;
server.sin_port = htons( PORT );
server.sin_addr.s_addr = inet_addr("0.0.0.0");
printf( "bind = %d SFD: %d\n" , bind( sfd , (struct sockaddr *)&server , sizeof(server) ) , sfd );
////////////////////////////////
for( num = 0; num < numberOfThreads; num++ )
{
printf("Thread Created!!!\n");
rc = pthread_create( &thread , NULL, subserverThreadFunction, (void *) sfd );
pthread_join( thread , NULL );
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
///////////////////////////////////
///////////////////////////////////
//printf( "Please enter the query from the client!\n");
/*
recvfrom( sfd , buffer1 , 1024 , 0 , (struct sockaddr *)&client , &l );
printf( "Message from client: %s\n" , buffer1);
printf( "Message to client: " );
for( int i = 0; i < 5; i++ )
{
if( strcmp( listOfVideos[i] , buffer1 ) == 0 )
{
printf( "\nOne match found: %s" , listOfVideos[i] );
sendto( sfd , listOfVideos[i] , strlen( listOfVideos[i] ) , 0 , (struct sockaddr *)&client , l );
}
}
sendto( sfd , "" , strlen( "" ) , 0 , (struct sockaddr *)&client , l );
*/
///////////////////////////////////
//sendto( sfd , buffer2 , strlen(buffer2) , 0 , (struct sockaddr *)&client , l );
close(sfd);
printf( "\n" );
pthread_exit(NULL);
return 0;
}
我的子服务器代码如下:
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
#include <fcntl.h>
int PORT = 8889;
int main()
{
int sfd = 0,l = 0, breaker = 0 , i = 0;
int number = 1;
char *buffer1[2] , end[4] = "end";
buffer1[0] = "1,0.0.0.0,8888,hello.mp4,10.0";
buffer1[1] = "1,0.0.0.0,8888,world.mp4,20.0";
struct sockaddr_in ser;
sfd = socket( AF_INET , SOCK_DGRAM , 0 );
bzero( &ser , sizeof(ser) );
ser.sin_family = AF_INET;
ser.sin_port = htons( PORT );
inet_aton("0.0.0.0" , &ser.sin_addr);
while( breaker != 2 )
{
sendto( sfd , buffer1[i] , strlen( buffer1[i] ) , 0 , (struct sockaddr *)&ser , sizeof(ser) );
printf("\nString sent to server: %d" , i );
breaker++;
i++;
}
sendto( sfd , end , sizeof(end) + 1 , 0 , (struct sockaddr *)&ser , sizeof(ser) );
printf("\nData sent successful!");
close(sfd);
printf( "\n" );
return 0;
}
我现在停留了很长一段时间,我似乎无法弄清问题是什么。任何帮助都将非常感谢!
答案 0 :(得分:1)
如果没有pthread_join(),您的服务器例程会创建新线程,传入套接字文件描述符,然后立即继续并关闭新创建的套接字。
如果你创建多个线程,那么你需要做一些事情,比如将线程id存储在一个数组中,然后在它们之外连接它们。
最后一件事 - 你真的想将相同的套接字描述符传递给每个线程吗?如果你能建议我获得一份Unix网络编程,第1卷:套接字网络API(第3版),它将提供有关如何创建客户端/服务器应用程序的大量信息。