tcp_socket()
{
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
printf("Could not create socket\n");
}
puts("Socket created.......\n");
server.sin_addr.s_addr = inet_addr("172.210.110.10");
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
//Connect to remote server
con= connect(sock , (struct sockaddr *)&server , sizeof(server));
if(con<0)
{
perror("connect failed. Error\n");
return con;
}
puts("Connected\n");
err = pthread_create(&tid, NULL,reciever_port,(int*)sock);
if (err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
else
printf("\n Thread created successfully\n");
return 1;
}
void *reciever_port(int sockid)
{
unsigned char inbuf[MAX_REQUEST_LINES]="";
while(1)
{
memset(inbuf, 0, sizeof(inbuf));
rc=recv(sockid , inbuf , 1024 , 0);
if(rc<0)
{
puts("waiting .........\n");
exit(0);
}
else
{
for(i=0;i<rc;i++)
{
printf("%c",inbuf[i]);
}
}
我已经打开了一个客户端套接字并使用reciever_port
调用函数pthread_create
,在reciever_port
中,while循环不断接收,如果有任何数据来自服务器,但它不打印任何东西,都不能正常工作,而没有线程就可以了。
我错过了什么,或者有人能指出我正确的方向吗?
答案 0 :(得分:2)
您有指针转换问题:
err = pthread_create(&tid, NULL,reciever_port,(int*)sock);
这会将sock
整数的值转换为int *
指针。无法保证这实际上适用于所有平台(为什么通常有intptr_t *
。
这一行本身也应该引发编译器警告,因为reciever_port
的类型是
void *(*reciever_port)(int sockid);
虽然线程函数的类型是
void *(*start_routine)(void *);
我有点惊讶这实际上是编译的。你确实启用了警告,是吗?
在reciever_port()
中,您隐式将void *
- 伪装的int
转换回一个也不能保证有效的整数。
稍微清理一下:
int *thread_socket = calloc(1, sizeof(int));
*thread_socket = sock;
err = pthread_create(&tid, NULL,reciever_port,thread_socket);
if (err != 0) {
free(thread_socket);
[...]
}
[...]
void *reciever_port(void *arg)
{
int socket = *(int *)arg;
free(arg);
[...]
请注意,我对此代码中的“ callee释放调用者分配的内存”不满意。
当sock
是一个无法消失的静态变量时,可以避免无分配舞蹈,但这样你实际上可以创建多个线程。如果sock
是一个全局变量,则根本不需要将它作为参数传递。
您的线程代码可能还需要一些额外的工作:
void *
reciever_port(int sockid)
{
// MAX_REQUEST_LINES might be a misnomer, you don't read lines,
// you read individual bytes/chars.
unsigned char inbuf[MAX_REQUEST_LINES] = "";
while(1) {
memset(inbuf, 0, sizeof(inbuf));
// you really don't want 1024 as a magic number, here
rc = recv(sockid, inbuf, sizeof(inbuf) ,0);
if (rc < 0) {
perror("Error receiving data: ");
/* no need to kill everything when the thread exits */
return NULL;
} else {
for(i = 0;i < rc; i++) {
putc(inbuf[i]);
}
fflush(stdout);
}
}
}
请注意输出流的显式fflush()
。您可能无法看到任何输出,否则stdout
通常是行缓冲的,因此每个没有换行的写操作都会保留在内存中,直到缓冲区已满。