/* * Start a user-mode thread (i.e., a process), using given user context. * Returns pointer to the new thread if successful, null otherwise. */ struct Kernel_Thread* Start_User_Thread(struct User_Context* userContext, bool detached) { //lacki /* * Hints: * - Use Create_Thread() to create a new "raw" thread object * - Call Setup_User_Thread() to get the thread ready to * execute in user mode * - Call Make_Runnable_Atomic() to schedule the process * for execution */ //TODO("Start user thread"); struct Kernel_Thread *pKernel_Thread = Create_Thread(PRIORITY_NORMAL, detached); if (pKernel_Thread != 0) { Setup_User_Thread(pKernel_Thread, userContext); Make_Runnable_Atomic(pKernel_Thread); return pKernel_Thread; } else { DEBUG("ERROR: Start_User_Thread - not able to create thread"); return 0; } }
/* * Start a user-mode thread (i.e., a process), using given user context. * Returns pointer to the new thread if successful, null otherwise. */ struct Kernel_Thread* Start_User_Thread(struct User_Context* userContext, bool detached) { /* * Hints: * - Use Create_Thread() to create a new "raw" thread object * - Call Setup_User_Thread() to get the thread ready to * execute in user mode * - Call Make_Runnable_Atomic() to schedule the process * for execution */ struct Kernel_Thread* kthread; kthread = Create_Thread(PRIORITY_USER, detached); if (kthread != 0) { /* * Create the initial context for the thread to make * it schedulable. */ Setup_User_Thread(kthread, userContext); /* Atomically put the thread on the run queue. */ Make_Runnable_Atomic(kthread); } return kthread; }
DWORD WINAPI ThreadRecv(LPVOID lpParam){ Threadpackage package = *((Threadpackage *)lpParam); delete (Threadpackage *)lpParam; while(1){ //和不同客户端连接需要不同的通路 ACE_SOCK_Stream* ppeer = new ACE_SOCK_Stream; //会在这里阻塞,一旦和客户端连接则下去,进入线程,之后的所有处理在线程中运行,主线程等待下一个连接者 if(package.pacceptor->accept(*ppeer) != -1){ //连接之后由于可能有多个客户端所以需要多个线程,先把通路存入vec package.pmutex->Lock(); package.pvecIPPeer->push_back(ppeer); package.pmutex->Unlock(); //需要进入线程才需要给参数 Threadpackage* pClientPackage = new Threadpackage; pClientPackage->pThis = package.pThis; pClientPackage->ppeer = ppeer; pClientPackage->RecvMaxLength = package.RecvMaxLength; pClientPackage->pmutex = package.pmutex; pClientPackage->pvecIPPeer = package.pvecIPPeer; pClientPackage->ifUseJson = package.ifUseJson; DWORD ThreadID = 0; Create_Thread(ThreadClient,pClientPackage,ThreadID); } } }
DWORD WINAPI ThreadRecv(LPVOID lpParam){ Threadpackage package = *((Threadpackage *)lpParam); delete (Threadpackage *)lpParam; char* pbuf = (char *)calloc(package.RecvMaxLength,1); while(1){ int RecvLength = package.ppeer->recv(pbuf,package.RecvMaxLength); //接收数据 //可能在结束的时候会有一个空字符串发过来 if(RecvLength >= 0){ pbuf[RecvLength] = 0; //一旦接受到信息之后应该让处理活动在线程中执行,主线程依然等待接收,线程内加锁 //好处是如果虚函数内有等待卡死等操作时不会影响其他消息的接收 DWORD ThreadID = 0; package.pBuf = (char *)calloc(RecvLength + 1,1); memcpy(package.pBuf,pbuf,RecvLength); package.RecvLength = RecvLength; Threadpackage *ppackage = new Threadpackage; *ppackage = package; Create_Thread(ThreadRecvHandling,ppackage,ThreadID); } //如果服务器与客户端断连recv立刻取消阻塞返回-1 else{ Sleep(package.ReconnectTime * 1000); //如果断连则循环断线重连,一旦断线ppeer不可复用,需要重新申请 package.pmutex->Lock(); delete package.pThis->ppeer; package.pThis->ppeer = new ACE_SOCK_Stream; package.ppeer = package.pThis->ppeer; package.pThis->pconnector->connect(*(package.ppeer),*(package.paddr),package.ptimeout); package.pmutex->Unlock(); } } free(pbuf); return 0; }
BOOL CAceTCPClient::init(CString strIP,int port,int ConnectWaitTime,int RecvMaxLength,int ReconnectTime,int ifUseJson){ paddr = new ACE_INET_Addr(port,strIP); pconnector = new ACE_SOCK_Connector; ptimeout = new ACE_Time_Value(ConnectWaitTime,0); ppeer = new ACE_SOCK_Stream; this->ifUseJson = ifUseJson; CheckKeyClient = 0; int nResult = pconnector->connect(*ppeer,*paddr,ptimeout); if(nResult != 0){ AfxMessageBox("连接失败"); return 0; } //线程参数 Threadpackage *ppackage = new Threadpackage; ppackage->pmutex = &mutex; ppackage->ppeer = ppeer; ppackage->pThis = this; ppackage->RecvMaxLength = RecvMaxLength; ppackage->ifUseJson = ifUseJson; ppackage->paddr = paddr; ppackage->ptimeout = ptimeout; ppackage->ReconnectTime = ReconnectTime; //进入线程,用于后台接收服务器发来的数据 DWORD ThreadID = 0; Create_Thread(ThreadRecv,ppackage,ThreadID); return 1; }
void CCheckUSB::CheckUSBOut(){ ifCheckOut = 1; //默认是在循环中 stateOut = 1; DWORD ThreadID = 0; Create_Thread(CheckOut,0,ThreadID); return; }
void CCheckUSB::CheckUSBIn(){ ifCheckIn = 1; //默认在循环中 stateIn = 1; DWORD ThreadID = 0; Create_Thread(CheckIn,0,ThreadID); return; }
/* * Start a kernel-mode-only thread, using given function as its body * and passing given argument as its parameter. Returns pointer * to the new thread if successful, null otherwise. * * startFunc - is the function to be called by the new thread * arg - is a paramter to pass to the new function * priority - the priority of this thread (use PRIORITY_NORMAL) for * most things * detached - use false for kernel threads */ struct Kernel_Thread* Start_Kernel_Thread( Thread_Start_Func startFunc, ulong_t arg, int priority, bool detached ) { struct Kernel_Thread* kthread = Create_Thread(priority, detached); if (kthread != 0) { /* * Create the initial context for the thread to make * it schedulable. */ Setup_Kernel_Thread(kthread, startFunc, arg); /* Atomically put the thread on the run queue. */ Make_Runnable_Atomic(kthread); } return kthread; }
DWORD WINAPI ThreadClient(LPVOID lpParam){ Threadpackage ClientPackage = *((Threadpackage *)lpParam); delete (Threadpackage *)lpParam; int nReceiveLength = 0; char* pbuf = (char *)calloc(ClientPackage.RecvMaxLength,1); //接收客户端发送的数据,会在这里阻塞,一旦和客户端断开则立刻取消阻塞返回0,再运行则返回-1 while((nReceiveLength = ClientPackage.ppeer->recv(pbuf,ClientPackage.RecvMaxLength)) != -1){ //如果传过来一个空数据则不处理,在断连时会传一个空数据 if(nReceiveLength > 0){ pbuf[nReceiveLength] = 0; //一旦接收到内容则放入线程中处理,防止因为虚函数的处理内容卡死或等待 Threadpackage* pClientPackage = new Threadpackage; ClientPackage.pBuf = (char *)calloc(nReceiveLength + 1,1); memcpy(ClientPackage.pBuf,pbuf,nReceiveLength); ClientPackage.nReceiveLength = nReceiveLength; *pClientPackage = ClientPackage; DWORD ThreadID = 0; Create_Thread(ThreadClientHandling,pClientPackage,ThreadID); } //如果发送了空数据则必须向客户端发送一条任意数据才能让通路知道已经断连返回-1退出循环 else ClientPackage.ppeer->send("",1); } //一旦和客户端断开则该通路的recv默认都会返回-1了,所以直接关闭通路 ClientPackage.ppeer->close(); //加锁把类中保存通路的vector里删掉断掉的通路 ClientPackage.pmutex->Lock(); int i = -1; while(i++ != ClientPackage.pvecIPPeer->size() - 1){ if(ClientPackage.pvecIPPeer->at(i) == ClientPackage.ppeer) break; } if((unsigned int)i < ClientPackage.pvecIPPeer->size()){ ClientPackage.pvecIPPeer->erase(ClientPackage.pvecIPPeer->begin() + i); } else AfxMessageBox("通路已被释放"); ClientPackage.pmutex->Unlock(); free(pbuf); delete ClientPackage.ppeer; return 0; }
BOOL CAceTCPServer::init(int port,int RecvMaxLength,int ifUseJson){ ACE_INET_Addr port_to_listen(port); //绑定的端口 if(pacceptor->open(port_to_listen,1) == -1){ //绑定端口 AfxMessageBox("打开端口失败"); return 0; } this->ifUseJson = ifUseJson; //开一个线程用于阻塞接收 //添加一个锁,用户处理的虚函数必须要上锁,当多个客户端连接的时候,必须先处理完一个客户端的数据才能处理第二个 Threadpackage* pThreadRecvPac = new Threadpackage; pThreadRecvPac->pmutex = &mutex; pThreadRecvPac->RecvMaxLength = RecvMaxLength; pThreadRecvPac->pThis = this; pThreadRecvPac->pacceptor = pacceptor; pThreadRecvPac->pvecIPPeer = &vecIPPeer; pThreadRecvPac->ifUseJson = ifUseJson; //开线程 DWORD ThreadID = 0; Create_Thread(ThreadRecv,pThreadRecvPac,ThreadID); return 1; }
DC_ID CScriptModule::Call_Threaded_Script_Method(const char* func, const char* sig, ...) { va_list vl; int narg, nres; // New Thread CThread* pNewThread = Create_Thread(); lua_State* pThread = pNewThread->m_pState; // Push the method lua_getglobal( pThread, func ); va_start(vl, sig); narg = 0; while (*sig) { switch (*sig++) { case 'd': { lua_pushnumber(pThread, va_arg(vl, double)); break; } case 'i': { lua_pushnumber(pThread, va_arg(vl, int)); break; } case 's': { lua_pushstring(pThread, va_arg(vl, char *)); break; } case '>': { goto endwhile; } default: { break; } } narg++; luaL_checkstack(pThread, 1, "Too many arguments\n"); } endwhile: nres = strlen(sig); int status = lua_resume( pThread, NULL, narg ); // Thread exited normally if( status == 0 ) { DLog(LOG_SCRIPT, "Thread exited normally\n"); } else if( status == LUA_YIELD ) { DLog(LOG_SCRIPT, "Thread yielded\n"); } else { // TODO: check the stack here string errmsg = lua_tostring( pThread, -1 ); Log( LOG_SCRIPT, "Error running thread: %s\n", errmsg.c_str() ); lua_pop( pThread, 1 ); return DC_INVALID_ID; } nres = -nres; while (*sig) { switch (*sig++) { case 'd': { if (!lua_isnumber(pThread, nres)) { DLog(LOG_SCRIPT, "Wrong result type\n"); } *va_arg(vl, double *) = lua_tonumber(pThread, nres); break; } case 'i': { if (!lua_isnumber(pThread, nres)) { DLog(LOG_SCRIPT, "Wrong result type\n"); } *va_arg(vl, int *) = (int)lua_tonumber(pThread, nres); break; } case 's': { if (!lua_isstring(pThread, nres)) { DLog(LOG_SCRIPT, "Wrong result type\n"); } *va_arg(vl, const char **) = lua_tostring(pThread, nres); break; } default: { DLog(LOG_SCRIPT, "Invalid option\n"); } } nres++; } va_end(vl); if( status ==0 ) { Destroy_Thread(pNewThread->GetID()); return DC_INVALID_ID; } else { return pNewThread->GetID(); } }
int main(int argc,char *argv[],char *envp[]) { if(argc != 3 && argc != 4){ fprintf(stderr,"%%./gnutella.exe gport hport or %%./gnutella.exe gport hport env\n"); fprintf(stderr, "gport is the gnutella connection port number.\n"); fprintf(stderr, "hport is the http connection port number.\n"); fprintf(stderr, "env is your environment.\n"); fprintf(stderr, " 0: Mac OS X with wired LAN(Default).\n"); fprintf(stderr, " 1: Mac OS X with wireless LAN.\n"); fprintf(stderr, " 2: Linux.\n"); fprintf(stderr, " 3: Windows.\n"); exit(-1); } /******************************************var****************************************/ //net int gnufd; int httpfd; int newfd; //select fd_set rdfds; //tmp_aadr struct sockaddr_in myskt,peerskt; struct in_addr tmp; //socklen_t my_sktlen = sizeof(myskt); socklen_t peer_sktlen = sizeof(peerskt); //analyze char cmd[CMD_SIZE]; Cmd_tbl *pcmd; char *p; int myargc; char *myargv[ARGV_SIZE]; /******************************************var end****************************************/ /*****************************************set addr*********************************/ char *os = MAC_WIRED; if(argc >= 4){ int env = atoi(argv[3]); if(env == 0) os = MAC_WIRED; if(env == 1) os = MAC_WIRELESS; if(env == 2) os = LINUX; if(env == 3) os = WIN; } myip = tmp.s_addr = GetMyIpAddr(os); memset(&myskt,0,sizeof(myskt)); myskt.sin_addr.s_addr = Get_Myip(); myskt.sin_family = AF_INET; //default myportg = GNU_PORT; myskt.sin_port = htons(GNU_PORT);//GNU port 6346(Big) if(argc >= 3){//%a.out port1 port2 myportg = atoi(argv[1]); myskt.sin_port = htons(myportg); } if((gnufd = Gnutella_Create_Waitfd(myskt)) < 0){//Create Gnutella socket fprintf(stderr,"Cnutella_Create_Waitfd() error!\n"); exit(-1); } //default myporth = HTTP_PORT; myskt.sin_port = htons(HTTP_PORT);//HTTP port 10010(Big) if(argc >= 3){//%a.out port1 port2 myporth = atoi(argv[2]); myskt.sin_port = htons(myporth); } if((httpfd = Gnutella_Create_Waitfd(myskt)) < 0){//Create HTTP socket fprintf(stderr,"Cnutella_Create_Waitfd() error!\n"); exit(-1); } //default share_dir = DEFAULT_DIR; /*****************************************set addr end*********************************/ //init Init_Local_Sharelist(Get_Share_Dir()); Init_Net_Sharelist(); Init_Thtbl(); Init_Ping_List(); Init_Query_List(); myspeed = DEFAULT_MYSPEED; //print printf("+++IP+++ %s\n",inet_ntoa(tmp)); printf("+++gnuport+++ %d\n",Get_Myportg()); printf("+++httpport+++ %d\n",Get_Myporth()); printf("+++shared dir+++ %s\n",Get_Share_Dir()); printf("+++shared file num+++ %d\n",Get_Local_Share_Num()); // printf("+++responding speed+++ %d\n",Get_Myspeed()); Print_Local_Sharelist(); /*****************************while start*************************/ while(1){ fflush(stdin); fprintf(stderr,"[gnutella]%%");//prompt FD_ZERO(&rdfds);//init FD_SET(STDIN_FD,&rdfds);//keyboard FD_SET(gnufd,&rdfds);//gnutella FD_SET(httpfd,&rdfds);//http if(select(httpfd+1,&rdfds,NULL,NULL,NULL) < 0){//monitor & block perror("select"); continue; } if(FD_ISSET(STDIN_FD,&rdfds)){//from keyboard,input cmd //analyze if(fgets(cmd,sizeof(cmd),stdin) == NULL){ if(feof(stdin)) fprintf(stderr,"EOF pushed\n"); else fprintf(stderr,"fgets() error!\n"); continue; } if((p = Search_Char(cmd,'\n',sizeof(cmd))) == NULL){ fprintf(stderr,"Search_Char() error!\n"); continue; } *p = '\0'; getargs(cmd,&myargc,myargv); if(myargc <= 0) continue; //analyze end for(pcmd = cmdtbl; pcmd->cmd != NULL; pcmd++){ if(strcmp(myargv[0],pcmd->cmd) == 0){ if( (*pcmd->pf)(myargc,myargv) < 0){//cmd handler fprintf(stderr,"cmd %s error\n",pcmd->cmd); } break; } } if(pcmd->cmd == NULL) fprintf(stderr,"Unknown Command\n"); } if(FD_ISSET(gnufd,&rdfds)){//from gnutella socket memset(&peerskt,0,sizeof(peerskt)); peer_sktlen = sizeof(peerskt); if((newfd = accept(gnufd,(struct sockaddr *)&peerskt,&peer_sktlen)) < 0){ perror("accept"); continue; } if(Gnutella_Accept(newfd) < 0){//bad msg or timeout fprintf(stderr,"gnutella accept fail!!\n"); close(newfd); continue; } printf("gnutella accept OK!!\n"); /* create thread */ if(Create_Thread(newfd,TYPE_GNU) < 0){//thread create error fprintf(stderr,"Create_Gnu_Thread() error!\n"); close(newfd); continue; } printf("create thread success!!\n"); } if(FD_ISSET(httpfd,&rdfds)){//from http socket printf("coming http port!\n"); memset(&peerskt,0,sizeof(peerskt)); peer_sktlen = sizeof(peerskt); if((newfd = accept(httpfd,(struct sockaddr *)&peerskt,&peer_sktlen)) < 0){ perror("accept"); continue; } /* create thread */ if(Create_Thread(newfd,TYPE_HTTP) < 0){//thread create error fprintf(stderr,"Create_Http_Thread() error!\n"); close(newfd); continue; } printf("create thread success!!\n"); } } /*****************************while end*************************/ }