gpt4 book ai didi

c - Recv() 不在单独的线程中工作,C 套接字编程

转载 作者:太空宇宙 更新时间:2023-11-04 04:31:15 24 4
gpt4 key购买 nike

我在使用线程的 C 程序中 recv() 函数返回 -1 时遇到一些问题。该程序的基础是在一个线程中接收一些请求数据包,并让第二个线程向所有注册的客户端发送多播。

下面是我的服务器的代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <arpa/inet.h>
#include <pthread.h>

#define SERVER_PORT 5654
#define MAX_LINE 256
#define MAX_PENDING 5

/*structure of the packet*/
struct packet{
short type;
char data[MAX_LINE];
};
struct data_packet{
short header;
char data[MAX_LINE];
};
/* structure of Registration Table */
struct registrationTable{
int port;
char name[MAX_LINE];
int req_no;
};
struct global_table{
int sockid;
int reqno;
};

void *join_handler(struct global_table *rec){

int new_s;
struct packet packet_reg;
new_s = rec->sockid;


printf("In thread: %i\n",new_s);
printf("In thread: %i\n",rec->reqno);

if(recv(new_s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\ncouldnt receive first reg packet\n");
exit(1);
}


pthread_exit(NULL);
}
int main(int argc, char* argv[])
{
/* initilizing all of the packets*/
struct packet packet_reg;
struct registrationTable table[10];
struct global_table record[20];
struct sockaddr_in sin;
struct sockaddr_in clientAddr;
char buf[MAX_LINE];
int s, new_s;
int len;
int i;
struct hostent *he;
struct in_addr **addr_list;
pthread_t threads[2];

/* setup passive open */
if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0){
perror("tcpserver: socket");
exit(1);
}

/* build address data structure */
bzero((char*)&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);

if(bind(s,(struct sockaddr *)&sin, sizeof(sin)) < 0){
perror("tcpclient: bind");
exit(1);
}
listen(s, MAX_PENDING);

/* wait for connection, then receive and print text */
while(1){

if((new_s = accept(s, (struct sockaddr *)&clientAddr, &len)) < 0){
perror("tcpserver: accept");
exit(1);
}
/* print the port of the client*/
printf("\n Client's port is %d \n", ntohs(clientAddr.sin_port));

/* receive the first registration packet*/
if(recv(new_s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\ncouldnt receive first reg packet\n");
exit(1);
}

struct global_table client_info;

client_info.sockid = ntohs(clientAddr.sin_port);
client_info.reqno = 1;

pthread_create(&threads[0],NULL,join_handler, &client_info);

}

}

客户:

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>

#define SERVER_PORT 5654
#define MAX_LINE 256

/*structure of the packet*/
struct packet{
short type;
char data[MAX_LINE];
};
struct data_packet{
short header;
char data[MAX_LINE];
};
int main(int argc, char* argv[])
{

struct packet packet_reg;
struct hostent *hp;
struct sockaddr_in sin;
char *host;
char buf[MAX_LINE];
int s;
int len;
char hostname[1024];
hostname[1023] = '\0';

if(argc == 2){
host = argv[1];
}
else{
fprintf(stderr, "usage:newclient server\n");
exit(1);
}

/* translate host name into peer's IP address */
hp = gethostbyname(host);
if(!hp){
fprintf(stderr, "unkown host: %s\n", host);
exit(1);
}

/* active open */
if((s = socket(PF_INET, SOCK_STREAM, 0)) < 0){
perror("tcpclient: socket");
exit(1);
}

/* build address data structure */
bzero((char*)&sin, sizeof(sin));
sin.sin_family = AF_INET;
bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
sin.sin_port = htons(SERVER_PORT);


if(connect(s,(struct sockaddr *)&sin, sizeof(sin)) < 0){
perror("tcpclient: connect");
close(s);
exit(1);
}
/* main loop: get and send lines of text
all you have to do to start the program is
enter any key */
while(fgets(buf, sizeof(buf), stdin)){

/* Find the hostname and print it*/
gethostname(hostname, 1023);
printf("Hostname: %s\n", hostname);

/* populate the info for the first registration packet*/
packet_reg.type = htons(121);
strcpy(packet_reg.data,hostname);

/*send the registration packet to the server*/
if(send(s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\nsend failed\n");
exit(1);
}

/* Print the contents of the first registration packet*/
printf("Sent 1st reg packet data: %s\n",packet_reg.data );
printf("Sent 1st reg packet type: %i\n",ntohs(packet_reg.type));

/* create the second registration packet.
I created separate packets for this so
it was clearer*/
packet_reg.type = htons(121);
strcpy(packet_reg.data,hostname);

/*send the second registration packet to the server*/
if(send(s,&packet_reg,sizeof(packet_reg),0)<0){
printf("\nsend failed\n");
exit(1);
}

/* Print the contents of the second registration packet*/
printf("Sent 2nd reg packet data: %s\n",packet_reg.data );
printf("Sent 2nd reg packet type: %i\n",ntohs(packet_reg.type));
}
}

基本上,我正在创建连接并等待接收第一个注册数据包 (packet_reg)。这有效,我收到了数据包。然后我将程序的控制权发送给线程。然而,虽然“rec”变量正确传递了信息,但随后的接收不起作用并以小于 0 的值退出。

其他信息:数据包发送和接收都正确,但是客户端的端口,打印自

 printf("\n Client's port is %d \n", ntohs(clientAddr.sin_port)); 

被列为 0。我不确定这是否是一个问题,但是当所有接收都在 main 函数中时代码工作正常。

另一个问题可能是我收到以下警告:

passing argument 3 pf pthread_create from incompatible pointer type expected    'void * (*) (void *)' but argument of type 'void * (*) (struct  global_table*)'

我研究了这个警告,知道它与接收无效数据然后进行转换有关。但是,当我从那里打印以检查时,数据已正确发送到线程。

基本上,问题是虽然我可以使用相同的语句从线程外的客户端接收数据包,但当我在线程内时,数据包没有收到并且 recv() 返回 -1。

最佳答案

我不小心将接收设置为端口而不是套接字。我是个假人。我知道你们中的很多人都在告诉我关于 TCP 约定的代码构建有多糟糕。我正在为一项作业编写代码,教授告诉我们这是这样做的方法,我无能为力。

关于c - Recv() 不在单独的线程中工作,C 套接字编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35995263/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com