我在C中编写了一个基本的聊天程序。我已经为它构建了框架,但我无法继续进行,直到我修复了用户名错误。我的客户端和服务器正在通信,但是当我输入用户名时,服务器会显示先前输入的用户名。
EX:客户端程序进入Joe:服务器没有显示任何内容
客户端程序进入Tom:服务器显示"输入的用户名:Joe"
客户端程序进入Rob:服务器显示"用户名输入:Tom"
这是client.c
#include <sys/socket.h>
#include <pthread.h>
#include <time.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define SA struct sockaddr
#define MAXLINE 4096
//void leave(int sig); /* Things to do after signal handler is called*/
void error(const char *msg)
{
perror(msg);
exit(0);
}
/*Routine to send data*/
static void *do_send(void *arg)
{
int fd = *(int*)(arg); //Socket File Descriptor
char payload[512];
for(; ;) {
scanf("%s\r\n\n", payload);
write(fd, payload, sizeof(payload));
//Choose an available client’s username and send it to the server
//if ( the peer is ready to chat)
//for(; ;) {
//Code to send msg to its peer
//}
}
pthread_exit((void *)0);
}
/*Routine to receive data*/
static void *do_recv(void *arg)
{
int fd = *(int*)(arg);
char payload[512];
for(; ;) {
//Code to receive data
read(fd, payload, sizeof(payload));
//Print data
printf("%s\n", payload);
}
pthread_exit((void *)0);
}
int main(int argc, char **argv)
{
//Declare variables
int sockfd, n;
char recvline[MAXLINE+1];
struct sockaddr_in servaddr;
int status;
pthread_t chld_thr1, chld_thr2;
//Create socket.
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
error("Socket error");
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(1024);
//Send a connection request to server
if(connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
{
error("Connect error");
}
//Register username
/* Create a thread to send data */
pthread_create(&chld_thr1, NULL, do_send, (void *)&sockfd);
/* Create a thread to receive data */
pthread_create(&chld_thr2, NULL, do_recv, (void *)&sockfd);
//pthread_join(do_send, NULL);
//Close connection and exit
//Loops so program doesn't close
for(; ;){
}
}
这是server.c
#include <sys/socket.h>
#include <pthread.h>
#include <time.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Function prototypes and global variables */
#define SA struct sockaddr
#define LISTENQ 1024
/*Function executed by the new thread */
static void *do_child(void *arg)
{
//Declare variables
int fd = *(int*)(arg); //Socket Descriptor
char payload[512];
int list = 1;
int chat = 2;
int exit = 3;
int bytesRead = 0;
//Initial verification and registration codes
strcpy(payload, "Please enter your username:");
write(fd, payload, sizeof(payload));
for(; ;) {
//Receive messages from client
//Code to receive data
bytesRead = read(fd, payload, sizeof(payload));
//Print data
if (bytesRead > 0){
printf("Username entered: %s\n", payload);
}
//Check the msg_type of the message
//if(m1.msg_type == list)
//Send the list of available clients
//if(m1.msg_type ==chat)
//Forward messages to the peer that a client wants to chat with you
//if(m1.msg_type == chatMessage)
//Forward messages to its peer
//if(m1.msg_type == exit)
//Remove the client from the client list. Close the client connection
}
pthread_exit((void *)0);
}
int main(int argc, char *argv[]) {
//Declare Variables
int listenfd, connfd; //Socket ID's
struct sockaddr_in servaddr;
pthread_t chld_thr;
char payload[512];
//Create Socket
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(1024);
//Bind to the Address and Port Number Pair
bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
//Listen
listen(listenfd, LISTENQ);
for(; ;) {
connfd = accept(listenfd, (SA *) NULL, NULL);
if (connfd > 0){
strcpy(payload, "Connection Accepted");
printf("%s\n", payload);
/*Create a new thread to handle the connections. */
pthread_create(&chld_thr, NULL, do_child, (void *)&connfd);
}
else
printf("%s\n", "No connection could be made.");
}
//Close listen connection and exit.
}
答案 0 :(得分:1)
如果协议是“你总是发送和接收512字节”,那么你需要替换它:
bytesRead = read(fd, payload, sizeof(payload));
和此:
read(fd, payload, sizeof(payload));
有了这个:
bytesRead = 0;
do
{
ssize_t j = read(fd, payload + bytesRead, 512 - bytesRead));
if (j <= 0)
{
bytesRead = -1;
break;
}
bytesRead += j;
} while (bytesRead < 512);
如果那不是协议,那么它是什么?
我认为你不关心安全问题。但是如果你这样做,你需要考虑发送的512字节可能不包含终结符的可能性。
另请参阅我对accept
与复制其参数的线程之间的竞争条件的评论。
答案 1 :(得分:1)
简单....
变化: scanf(&#34;%s \ r \ n \ n&n&#34;,有效载荷);
于: scanf(&#34;%s&#34;,有效载荷);