再度杯具,socket多线程编程!

2540546520 2010-12-09 02:39:05
现在是这样的,界面上就只有一个按钮 “监听” 按钮点击事件如下

int ListenClient()

{
int temp;
InitSocket();
memset(&Th_Socket,0,sizeof(Th_Socket));
if ((pthread_create(&Th_Socket,0,Socket_Thread,NULL))<0)
printf("Create Thread failure\n");
else
printf("Create Thread success\n");
return( Pt_CONTINUE );

}
为了防止点击按钮程序卡死,已经把监听循环放在新创建的线程 Th_Socket中了,现在问题出来了
假如现在有一个客户端连接过来,那我是就要在 Th_Socket 线程中再创建一个线程了来处理这个链接了是吧,而Th_socket继续监听,但是我在Th_Socket的线程函数中再创建线程 服务端不知道为什么取不到数据?
哪位大牛知道,或者说我的做法是不对的?? 请指正,谢谢!
...全文
118 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
2540546520 2010-12-09
  • 打赏
  • 举报
回复
哪里出问题 大家指正下
if (pthread_create(&Th_Child,0,talk_to_client,(void *)msgsock)<0)
printf("Create Thread failure\n");
else
printf("Create Thread success\n");

是创建这个线程后 进入这个函数后 但是读不到buf中的内容
2540546520 2010-12-09
  • 打赏
  • 举报
回复
代码写得有点乱 没办法了 大家将就看看吧 谢谢

#include <sys/time.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

/* Local headers */
#include "ablibs.h"
#include "abimport.h"
#include "proto.h"
PtArg_t args[2];

#define TRUE 1
#define MaxClient 20;
#define DATA "QNX,Windows_Socket_TestProgram"

pthread_t Th_Socket;
pthread_mutex_t mut;
int number=0,i;
pthread_cond_t count_test;
int sock,length;
struct sockaddr_in server;
fd_set ready;
pthread_t Ary_ThChild[20];
pthread_t Th_Child;
void InitSocket()
{
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("opening stream socket");
exit(1);
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = 9600;
if (bind(sock, &server, sizeof(server))) {
perror("binding stream socket");
exit(1);
}

length = sizeof(server);
if (getsockname(sock, &server, &length)) {
perror("getting socket name");
exit(1);
}
printf("Socket has port #%d\n", ntohs(server.sin_port));
listen(sock, 5);
}

void *talk_to_client(void * clientsocket)
{
char buf[1024];
int rval;
int msgsock=(int)clientsocket;
do {
memset(buf, 0, sizeof(buf));
if ((rval = read(msgsock, buf, sizeof(buf))) < 0)
{
printf("...........%s\n", buf);
printf("reading stream message\n");
}
//perror("reading stream message");
else if (rval == 0)
{
perror("Ending connection\n");
}
else
{
if (send(msgsock,DATA,sizeof(DATA),MSG_OOB) < 0)
perror("writing on stream socket");

//if (write(sock, DATA, sizeof(DATA)) < 0)
//perror("writing on stream socket");

printf("-->%s\n", buf);
}
} while (rval > 0);
}


void *Socket_Thread()
{
//PtSetResource(ABW_PtReciveStr,Pt_ARG_TEXT_STRING,"success",0);
int msgsock;
char buf[1024];
int rval;
struct timeval to;
int Th_Res;

do {
FD_ZERO(&ready);
FD_SET(sock, &ready);
to.tv_sec = 5;
if (select(sock + 1, &ready, 0, 0, &to) < 0) {
perror("select");
continue;
}
if (FD_ISSET(sock, &ready)) {
msgsock = accept(sock, (struct sockaddr *)0, (int *)0);
if (msgsock == -1)
perror("accept");
else
{

memset(&Th_Child,0,sizeof(Th_Child));
if (pthread_create(&Th_Child,0,talk_to_client,(void *)msgsock)<0)
printf("Create Thread failure\n");
else
printf("Create Thread success\n");
}
close(msgsock);
};
} while (TRUE);
}

int
ListenClient( PtWidget_t *widget, ApInfo_t *apinfo, PtCallbackInfo_t *cbinfo )

{
/* eliminate 'unreferenced' warnings */
widget = widget, apinfo = apinfo, cbinfo = cbinfo;
int temp;
InitSocket();
memset(&Th_Socket,0,sizeof(Th_Socket));
if ((pthread_create(&Th_Socket,0,Socket_Thread,NULL))<0)
printf("Create Thread failure\n");
else
printf("Create Thread success\n");
return( Pt_CONTINUE );

}
木木0o0欧尼 2010-12-09
  • 打赏
  • 举报
回复
如下代码你可以借鉴一下:
/*******************************************************************************
* Function Name : Start_Modubus_Routine
* Description : the function is use to server the accept the new client
* Input : void* serverFd
* Output : None;
* Return : None;
*******************************************************************************/
void* Start_Server_Routine(void *arg)
{
struct sockaddr_in ServerAddr;
INT16S ServerFd;
INT16S Result;
INT16S shmid;
INT8U i = 0;
pthread_t AcceptThread;
pthread_t ModubusThread;


//创建一个socket
ServerFd = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

//复用端口
INT16S opt = 1;
setsockopt(ServerFd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

//绑定socket
bzero(&ServerAddr, sizeof(struct sockaddr_in));
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(PORT);
ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
Bind(ServerFd, (struct sockaddr *)&ServerAddr, sizeof(struct sockaddr));

//监听
Listen(ServerFd, BACKLOG);

//创建线程接收连接信息
pthread_create(&AcceptThread, NULL, Start_Accpet_Routine, (void *)&ServerFd);


while(1)
{
}

pthread_cancel(AcceptThread);
//pthread_cancel(ModubusThread);
Close(ServerFd);

}

/*******************************************************************************
* Function Name : Start_Accpet
* Description : the function is use to server the accept the new client
* Input : void* serverFd
* Output : None;
* Return : None;
*******************************************************************************/
void* Start_Accpet_Routine(void *serverfd)
{
INT16S NewConnfd, ServerFd;
INT8U i = 0;
INT16S Result = 0;
socklen_t SinSize;
struct sockaddr_in ClientAddr;
ARG *Arg;
ServerFd = *((int *)serverfd);
SinSize = sizeof(struct sockaddr_in);

while(1)
{
NewConnfd = Accept(ServerFd, (struct sockaddr *)(&ClientAddr), &SinSize);
Arg = (ARG *)malloc(sizeof(ARG));
Arg->attribute_fd = NewConnfd;

memcpy(&Arg->attribute_addr, &ClientAddr, SinSize);

//创建线程读写操作
pthread_create(&threadBuffer[i], NULL, Start_RdWr_Routine, (void *)Arg);
pthread_detach(threadBuffer[i]);
printf("Creat a new connection from %s\n",inet_ntoa(ClientAddr.sin_addr));
}

}
/*******************************************************************************
* Function Name : Start_Rd_Wr
* Description : the function is use to server the new client read and write handle
* Input : void* arg
* Output : None;
* Return : None;
*******************************************************************************/
void* Start_RdWr_Routine(void *arg)
{
ARG NewArg;
INT16S ReadyNum;
pthread_t WriteThread,ReadFifoThread;
INT16S RecvNum;
INT16S Result;

NewArg.attribute_fd = ((ARG *)arg)->attribute_fd;
NewArg.attribute_addr = ((ARG *)arg)->attribute_addr;

//设置select
fd_set ReadFd, WriteFd;
FD_ZERO(&ReadFd);
FD_SET(NewArg.attribute_fd, &ReadFd);
FD_ZERO(&WriteFd);
FD_SET(NewArg.attribute_fd, &WriteFd);


pthread_create(&WriteThread, NULL, Start_Write_Routine, (void *)&NewArg);
//写循环
while(1)
{
fd_set WriteSet, ReadSet;
WriteSet = WriteFd;
ReadSet = ReadFd;

ReadyNum = Select(NewArg.attribute_fd + 1, &ReadSet, &WriteSet, NULL, NULL);


//ret = recv(...);
if(recv <= 0)
{
close(NewArg.attribute_fd);
if(FD_ISSET(NewArg.attribute_fd, &WriteSet))
{
printf("net close\n");
shutdown(NewArg.attribute_fd, 1);
pthread_cancel(WriteThread);

}
else
{
shutdown(NewArg.attribute_fd, 0);
}
break;

}
}

pthread_join(WriteThread, NULL);
pthread_join(ReadFifoThread, NULL);
free(arg);

pthread_exit(NULL);
}
/*******************************************************************************
* Function Name : Start_Write_Routine
* Description : the function is use to server the new client read and write handle
* Input : void* arg
* Output : None;
* Return : None;
*******************************************************************************/
void* Start_Write_Routine(void *arg)
{
ARG NewArg;
fd_set WriteFd,ReadFd;
INT16S ReadyNum;
INT8U SendBuff[MAXDATASIZE];
INT16S Result = 0, Ret = 0;

NewArg.attribute_fd = ((ARG *)arg)->attribute_fd;
NewArg.attribute_addr = ((ARG *)arg)->attribute_addr;
NewArg.attribute_clientnum = ((ARG *)arg)->attribute_clientnum;

FD_ZERO(&WriteFd);
FD_SET(NewArg.attribute_fd, &WriteFd);
FD_ZERO(&ReadFd);
FD_SET(NewArg.attribute_fd, &ReadFd);

while(1)
{
fd_set ReadSet,WriteSet;
ReadSet = ReadFd;
WriteSet = WriteFd;
ReadyNum = Select(NewArg.attribute_fd + 1, &ReadSet, &WriteSet, NULL, NULL);

//在这里添加要发送给客户端得内?
}
pthread_exit(NULL);
}
2540546520 2010-12-09
  • 打赏
  • 举报
回复
do {
FD_ZERO(&ready);
FD_SET(sock, &ready);
to.tv_sec = 5;
if (select(sock + 1, &ready, 0, 0, &to) < 0) {
perror("select");
continue;
}
if (FD_ISSET(sock, &ready)) {
msgsock = accept(sock, (struct sockaddr *)0, (int *)0);
if (msgsock == -1)
//perror("accept");
printf("accept\n");
else
{

memset(&Th_Child,0,sizeof(Th_Child));
if (pthread_create(&Th_Child,0,talk_to_client,(void *)msgsock)<0)
printf("Create Thread failure\n");
else
printf("Create Thread success\n");
}
close(msgsock);
};
} while (TRUE);


这段代码是放在一个线程函数里面的
木木0o0欧尼 2010-12-09
  • 打赏
  • 举报
回复
楼主应该在accept后开线程与客户端进行通信
2540546520 2010-12-09
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 jexbow 的回复:]
是不是一直在accept那阻塞着呢
[/Quote]
[Quote=引用 1 楼 bdmh 的回复:]
服务端要轮询去select有效地客户端socket,你可能是一直在接受第一个连接,根本没有理会后面的
[/Quote]
估计是一直塞着 那应该怎么改动代码呢 我是在accept后开线程负责和客户端的连接的
do {
FD_ZERO(&ready);
FD_SET(sock, &ready);
to.tv_sec = 5;
if (select(sock + 1, &ready, 0, 0, &to) < 0) {
perror("select");
continue;
}
if (FD_ISSET(sock, &ready)) {
msgsock = accept(sock, (struct sockaddr *)0, (int *)0);
if (msgsock == -1)
//perror("accept");
printf("accept\n");
else
{

memset(&Th_Child,0,sizeof(Th_Child));
if (pthread_create(&Th_Child,0,talk_to_client,(void *)msgsock)<0)
printf("Create Thread failure\n");
else
printf("Create Thread success\n");
}
close(msgsock);
};
} while (TRUE);
popo00fa 2010-12-09
  • 打赏
  • 举报
回复
是不是一直在accept那阻塞着呢
就想叫yoko 2010-12-09
  • 打赏
  • 举报
回复
按你的说法你可以在accept后开一个线程负责与这个客户端通信
也可以弄成短链接每次客户端都先连服务器,再接发数据
walkersfaint 2010-12-09
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 bdmh 的回复:]
服务端要轮询去select有效地客户端socket,你可能是一直在接受第一个连接,根本没有理会后面的
[/Quote]
+1
bdmh 2010-12-09
  • 打赏
  • 举报
回复
服务端要轮询去select有效地客户端socket,你可能是一直在接受第一个连接,根本没有理会后面的

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧