C客户端/服务器套接字错误

C客户端/服务器套接字错误,c,multithreading,sockets,client,C,Multithreading,Sockets,Client,我正在用C编写一个基本的聊天程序。我已经为它构建了框架,但在修复用户名错误之前,我无法继续。我的客户端和服务器正在通信,但当我输入用户名时,服务器会显示以前输入的用户名 例:客户端程序进入乔:服务器不显示任何内容 客户端程序输入Tom:server显示“用户名输入:Joe” 客户端程序进入Rob:服务器显示“输入的用户名:Tom” 这是客户机 #include <sys/socket.h> #include <pthread.h> #include <time.h&

我正在用C编写一个基本的聊天程序。我已经为它构建了框架,但在修复用户名错误之前,我无法继续。我的客户端和服务器正在通信,但当我输入用户名时,服务器会显示以前输入的用户名

例:客户端程序进入乔:服务器不显示任何内容

客户端程序输入Tom:server显示“用户名输入:Joe”

客户端程序进入Rob:服务器显示“输入的用户名:Tom”

这是客户机

#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(; ;){

}
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义SA结构sockaddr
#定义MAXLINE 4096
//无效休假(内部信号);/*调用信号处理程序后要做的事情*/
无效错误(常量字符*消息)
{
佩罗尔(味精);
出口(0);
}
/*发送数据的例程*/
静态void*do_send(void*arg)
{ 
int fd=*(int*)(arg);//套接字文件描述符
字符负载[512];
对于(;){
scanf(“%s\r\n\n”,有效载荷);
写入(fd、有效负载、sizeof(有效负载));
//选择可用客户端的用户名并将其发送到服务器
//如果(对方已准备好聊天)
//对于(;;){
//向其对等方发送消息的代码
//}
}
pthread_exit((void*)0);
}
/*接收数据的例程*/
静态void*do_recv(void*arg)
{
int fd=*(int*)(arg);
字符负载[512];
对于(;){
//接收数据的代码
读取(fd、有效载荷、sizeof(有效载荷));
//打印数据
printf(“%s\n”,有效载荷);
} 
pthread_exit((void*)0);
}
int main(int argc,字符**argv)
{   
//声明变量
int-sockfd,n;
char recvline[MAXLINE+1];
servaddr中的结构sockaddr_;
智力状态;
pthread_t chld_thr1,chld_thr2;
//创建套接字。
if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)
{
错误(“套接字错误”);
}
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(1024);
//向服务器发送连接请求
if(connect(sockfd,(SA*)&servaddr,sizeof(servaddr))<0)
{
错误(“连接错误”);
}
//注册用户名
/*创建一个线程以发送数据*/
pthread_create(&chld_thr1,NULL,do_send,(void*)&sockfd);
/*创建一个线程以接收数据*/
pthread_create(&chld_thr2,NULL,do_recv,(void*)&sockfd);
//pthread_join(do_send,NULL);
//关闭连接并退出
//循环以使程序不关闭
对于(;;){
}
}
这是服务器

#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.
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
/*函数原型和全局变量*/
#定义SA结构sockaddr
#定义Listenq1024
/*由新线程执行的函数*/
静态void*do_子对象(void*arg)
{
//声明变量
int fd=*(int*)(arg);//套接字描述符
字符负载[512];
int list=1;
int chat=2;
int exit=3;
int字节读取=0;
//初始验证和注册代码
strcpy(有效载荷,“请输入您的用户名:”);
写入(fd、有效负载、sizeof(有效负载));
对于(;;){
//从客户端接收消息
//接收数据的代码
bytesRead=读取(fd,有效载荷,sizeof(有效载荷));
//打印数据
如果(字节读取>0){
printf(“输入的用户名:%s\n”,有效负载);
}
//检查消息的消息类型
//if(m1.msg_type==列表)
//发送可用客户端的列表
//if(m1.msg_type==聊天)
//将客户端希望与您聊天的消息转发给对等方
//if(m1.msg_type==chatMessage)
//将消息转发给对等方
//如果(m1.msg_type==退出)
//从客户端列表中删除客户端。关闭客户端连接
}
pthread_exit((void*)0);
}
int main(int argc,char*argv[]){
//声明变量
int listenfd,connfd;//套接字ID
servaddr中的结构sockaddr_;
pthread_t chld_thr;
字符负载[512];
//创建套接字
listenfd=套接字(AF_INET,SOCK_STREAM,0);
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin\u addr.s\u addr=htonl(INADDR\u ANY);
servaddr.sin_port=htons(1024);
//绑定到地址和端口号对
绑定(listenfd,(SA*)&servaddr,sizeof(servaddr));
//听
听(listenfd,LISTENQ);
对于(;;){
connfd=accept(listenfd,(SA*)NULL,NULL);
如果(connfd>0){
strcpy(有效载荷,“接受连接”);
printf(“%s\n”,有效载荷);
/*创建一个新线程来处理连接。*/
pthread_create(&chld_thr,NULL,do_child,(void*)&connfd);
}
其他的
printf(“%s\n”,“无法建立连接”);
} 
//关闭连接并退出。
}
如果协议是“您始终发送和接收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);
bytesRead=0;
做
{
ssize_t j=读取(fd,有效负载+字节读取,512-字节读取));
如果(jSimple…)

更改: scanf(“%s\r\n\n”,有效载荷)

致:
scanf(“%s”,有效载荷);

您在
accept
intfd=*(int*)(arg)之间有一个竞争条件
。如果在线程可以取消引用您传递的指针之前,
接受
完成,您将看到两个线程从同一个套接字读取数据。@DavidSchwartz我从未遇到过争用条件或需要调试争用条件。有关如何在这种情况下执行此操作的任何提示?不要向线程传递指向b使用的值的指针y其他线程。相反,向它们传递值或分配值的副本,向它们传递一个指向该值的指针,并让它们取消分配。VG但您不想将bytesRead设置为-1,您想让它单独运行,也许除非出现错误。您希望在循环后读取的内容都可用。@EJP我的假设是他的协议是无效的“您必须写入/读取512字节”。少于512字节将构成不可理解的部分消息。此代码的目的是专门实现该协议。@DavidSchwartz我可以根据指令读/写任意长度的消息。是否替换客户端和服务器中的每个ByteRead和read函数?很清楚,每条消息都没有被咬512口,这是j