我在C语言中编写命令行聊天应用程序时遇到了一个未知问题,该应用程序具有以下功能。
"@Username Message"
实现应该实际上是可行的,我可以连接到服务器但是当我作为客户端发送消息时,没有任何反应。我认为线程可能存在问题。
提前致谢!
client.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pthread.h>
void error(const char *msg); //Funktion fuer errormessages
void *scocket_reader (void *sock); //Funktion fuer client thread socketreader
// Thread Funktion socket reader
void *scocket_reader (void *sock)
{
int n;
char buffer[256];
printf("Wurde gestartet warte auf nachrichten\n");
//Endloslesen vom Server
while(1)
{
bzero(buffer,256);
n = read(*(int *)sock,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s",buffer);
}
return NULL;
}
//Error Funktion
void error(const char *msg)
{
perror(msg);
exit(0);
}
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
//Thread init
pthread_t pt;
if (argc < 4) {
fprintf(stderr,"usage %s hostname port username\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
// Register @server
bzero(buffer,256);
strcpy(buffer,argv[3]);
//sende namen
n = write(sockfd,buffer,strlen(buffer));
bzero(buffer,256);
// Start Listener Thread
pthread_create (&pt, NULL, scocket_reader, &sockfd);
while(1)
{
//Nachrichten schreiben endlos
if ( fgets(buffer,255,stdin) != NULL )
if (buffer[0] != '\n')
{
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
}
bzero(buffer,256);
}
//socket schliessen
close(sockfd);
return 0;
}
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
void *client_scocket_reader (void *usernr); //Thread Funktion für socket reader
void error(const char *msg); //Error function
#define MAXUSER 10
// User Structur
struct User
{
socklen_t clilen;
struct sockaddr_in cli_addr;
int newsockfd;
char username[16];
};
struct User user[MAXUSER], tmpUser;
int user_anz = 0;
struct sockaddr_in serv_addr;
//Client Listener Thread -----------------------------------------------
void *client_scocket_reader (void *usernr)
{
int mynr = *(int *)usernr , n, foundone=0, i= 0;
char buffer[256], text[256], text_sp[256], uname[20], private_m[256];
char *splitter;
strcpy(text_sp,"000");
printf("Wurde gestartet ich bin User %d\n", mynr);
while(1)
{
foundone = 0;
bzero(buffer,256);
//Lesen und arten auf nachricht
n = read(user[mynr].newsockfd,buffer,255);
printf("----------%d-------------\n",n);
if (n <= 0)
{
printf("ERROR reading from socket\n");
user_anz--;
return NULL;
}
//Server Messages
if ( strstr(buffer, "@Server") )
{
splitter = strtok(buffer," ");
splitter = strtok(NULL," ");
if (splitter == NULL)
{
n = write(user[mynr].newsockfd, "Server: Not a cmd\n", 18);
continue;
}
if (strchr(splitter,'\n')) // Zeilenumbrüche entfernen
splitter[strlen(splitter)-1] = '\0';
printf("--->%s<--\n",splitter);
//Who Command
if (strcmp(splitter,"who") == 0)
{
n = write(user[mynr].newsockfd, "----Userlist----\n", 17);
for (i = 0 ; i < user_anz ; i++ )
{
strcpy(private_m, user[i].username);
strcat(private_m, "\n");
n = write(user[mynr].newsockfd, private_m, strlen(private_m));
}
n = write(user[mynr].newsockfd, "----------------\n", 17);
}
// logout
else if (strcmp(splitter,"logout") == 0)
{
n = write(user[mynr].newsockfd, "you are disconnected\n", 21);
user_anz--;
return NULL;
}
else if (strcmp(splitter,"history") == 0)
{
n = write(user[mynr].newsockfd, "Server: Not implemented\n", 24);
}
else if (strcmp(splitter,"help") == 0)
{
n = write(user[mynr].newsockfd, "----Help--------\n", 17);
n = write(user[mynr].newsockfd, "who\n",4);
n = write(user[mynr].newsockfd, "help\n",5);
n = write(user[mynr].newsockfd, "logout\n",7);
n = write(user[mynr].newsockfd, "history\n",8);
n = write(user[mynr].newsockfd, "----------------\n", 17);
}
else
n = write(user[mynr].newsockfd, "Server: Not a cmd\n", 18);
printf("I got an message\n");
//spring an ende der schleife da der rest nicht benoetigt wird
continue;
}
//Privat Messages
if ( buffer[0] == '@' )
{
//Suche durch alle user
for ( i = 0 ; i < user_anz ; i++)
{
bzero(uname,20);
//name zusamenbaun fuer vergleich
uname[0] = '@';
strcat(uname, user[i].username);
//namen suchen
if ( strstr(buffer, uname) )
{
printf("priv strstr->\n");
//Zusammenbau der Message
bzero(private_m,256);
strcpy(private_m, "Message from ");
strcat(private_m, user[mynr].username);
strcat(private_m, ": ");
strcat(private_m, buffer);
//SChreiben der nachricht zu jeweiligen user
n = write(user[i].newsockfd, private_m, strlen(private_m));
if (n < 0)
{
user_anz--;
printf("ERROR writing to socket\n");
return NULL;
}
foundone=1;
break;
}
}
if (foundone != 1)
{
printf("No user found\n");
// Antwort fuer User wurde nicht gefunden
n = write(user[mynr].newsockfd, "User Offline\n", 12);
if (n < 0)
{
user_anz--;
printf("ERROR writing to socket\n");
return NULL;
}
}
//spring an ende der schleife da der rest nicht benoetigt wird
continue;
}
// Messages weiterleiten an alle ausser mich
for ( i = 0 ; i < user_anz ; i++)
{
if ( i != mynr)
n = write(user[i].newsockfd, text, strlen(text));
if (n < 0)
{
user_anz--;
printf("ERROR writing to socketi\n");
return NULL;
}
}
// Für spezielle nachrichten Server antworten
if ( strcmp(text_sp, "000") != 0 )
{
strcat(text_sp,"\n");
for ( i = 0 ; i < user_anz ; i++)
{
n = write(user[i].newsockfd, text_sp, strlen(text_sp));
if (n < 0)
{
user_anz--;
printf("ERROR writing to socketi\n");
return NULL;
}
}
}
}
return NULL;
}
// Error Message mit exit
void error(const char *msg)
{
perror(msg);
exit(1);
}
int main(int argc, char *argv[])
{
int i,n;
int sockfd, portno;
char buffer[256],buffer2[256];
// Threads
pthread_t pt[MAXUSER];
// Argumentcheck
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\nUsage ./server portnumber\n");
exit(1);
}
printf("Init Socket\n");
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
printf("Init Server address\n");
// nuller reinschreiben
bzero((char *) &serv_addr, sizeof(serv_addr));
//port
portno = atoi(argv[1]);
//server address koniguration
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
printf("Bind server address\n");
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
printf("Init Listen\n");
listen(sockfd,5);
//--------------------------------------------------------
// init USERS to MAXUSERS
//--------------------------------------------------------
while(user_anz != MAXUSER)
{
printf("Waiting for Connects\n");
user[user_anz].clilen = sizeof(user[user_anz].cli_addr);
user[user_anz].newsockfd = accept(sockfd,
(struct sockaddr *) &user[user_anz].cli_addr,
&user[user_anz].clilen);
if (user[user_anz].newsockfd < 0)
error("ERROR on accept");
printf("Waiting for User1 registration\n");
bzero(buffer,256);
n = read(user[user_anz].newsockfd,buffer,255);
if (n < 0)
error("ERROR writing to socket");
printf("Sysmessage|| User %s connected\n", buffer);
strcpy(buffer2,"Hello ");
strcat(buffer2,buffer);
strcat(buffer2," you are now registrated!\n");
strcpy(user[user_anz].username, buffer);
n = write(user[user_anz].newsockfd,buffer2,strlen(buffer2));
if (n < 0)
error("ERROR writing to socket");
printf("Starting listener Thread\n");
//usernr = 0;
pthread_create (&pt[user_anz], NULL, client_scocket_reader, &user_anz);
user_anz++;
}
//Falls MAXUSER erreicht Threads joinen lassen damit der main thread net wegsemmelt
//--------------------------------------------------------
for ( i = 0 ; i < MAXUSER ; i++ )
pthread_join (pt[i], NULL);
// Sockets schliessen
//--------------------------------------------------------
for ( i = 0 ; i < MAXUSER ; i++)
close(user[i].newsockfd);
// Serversocket schliessen
close(sockfd);
return 0;
}
答案 0 :(得分:0)
我认为线程可能存在问题。
那是对的。 client_scocket_reader
main
与main
失去了比赛。 pthread_create (&pt[user_anz], NULL, client_scocket_reader, &user_anz);
user_anz++;
中容易出错的地点是
void *client_scocket_reader (void *usernr)
{
int mynr = *(int *)usernr , n, foundone=0, i= 0;
与
一起main
user_anz
将其复制到client_scocket_reader
之前,mynr
会增加client_scocket_reader
user[1]
使用来自user[0]
而非client_scocket_reader
user_anz
尝试从错误的文件描述符中读取快速修复:按值传递 pthread_create(pt+user_anz, NULL, client_scocket_reader, (void *)user_anz);
,而不是按引用传递。
int mynr = (int)usernr, n, foundone, i;
{{1}}