最近我一直在研究一些使用線程從服務器發送和接收消息的客戶端代碼。下面的代碼在運行時表現得很奇怪。輸入消息發送到服務器後,代碼完成任務,儘管「套接字已在使用」錯誤,服務器獲取它。但是,我嘗試發送給服務器的每個後續消息都不會立即收到,但它在客戶端程序終止時似乎都立即收到。地址已在使用中。
(此外,我敢肯定錯誤的是客戶端,如果一個評論的輸出功能的奇怪的行爲不能發揮。)
我怎樣才能解決這個問題?
客戶
#include <stdio.h>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string>
#include <iostream>
#include <errno.h>
#include <pthread.h>
void* input(void* ptr)
{
int on = 1;
bool *input_done = ((struct thread_args*)ptr)->process_done;
struct addrinfo *res = ((struct thread_args*)ptr)->result;
char msg[256];
int sock = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&on,sizeof(on));
bind(sock,res->ai_addr,res->ai_addrlen);
connect(sock,res->ai_addr,res->ai_addrlen);
cin.getline(msg,256);
if (msg[0] == '/') {exit(1);}
send(sock,msg,sizeof msg,0);
cout << "You:" << msg << endl;
*input_done = 1;
close(sock);
pthread_exit(NULL);
}
void* output(void* ptr)
{
int on = 1;
bool *output_done = ((struct thread_args*)ptr)->process_done;
struct addrinfo *res = ((struct thread_args*)ptr)->result;
char msg[256];
int sock = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
bind(sock,res->ai_addr,res->ai_addrlen);
connect(sock,res->ai_addr,res->ai_addrlen);
recv(sock,msg,sizeof msg,0);
cout << "Recieved:" << msg;
*output_done = 1;
close(sock);
pthread_exit(NULL);
}
void io_client()
{
//thread function variables
pthread_t t1,t2;
bool input_done = 1, output_done = 1;
//socket setup variables
struct addrinfo hints, *res;
memset(&hints,0,sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo("localhost","8080",&hints,&res);
//setting up structures to pass data to threaded functions
struct thread_args i_args, o_args;
i_args.result = res; i_args.process_done = &input_done;
o_args.result = res; o_args.process_done = &output_done;
while(1)
{
if (output_done)
{
pthread_create(&t2,NULL,output,&o_args);
output_done = 0;
}
if (input_done)
{
pthread_create(&t1,NULL,input,&i_args);
input_done = 0;
}
}
}
int main()
{
io_client();
}
服務器
void server()
{
struct addrinfo hints, *res;
int sock=-1, newsock=-1;
int length, on=1;
char **address_list; int entries = 0;
//fd_set read_fd;
//struct timeval timeout;
char buffer[100];
memset(&hints,0,sizeof hints);
res = NULL;
memset(&res,0,sizeof res);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo("localhost","8080",&hints,&res);
sock = socket(res->ai_family,res->ai_socktype,res->ai_protocol);
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&on,sizeof(on));
bind(sock,res->ai_addr,res->ai_addrlen);
listen(sock,10);
while(1)
{
struct sockaddr_storage addr;
char ipstr[INET6_ADDRSTRLEN];
socklen_t len;
len = sizeof addr;
newsock = accept(sock,NULL,NULL);
getpeername(newsock,(struct sockaddr*)&addr,&len);
struct sockaddr_in *s = (struct sockaddr_in*)&addr;
inet_ntop(AF_INET,&s->sin_addr,ipstr,sizeof ipstr);
length = 100;
setsockopt(newsock,SOL_SOCKET,SO_RCVLOWAT, (char*)&length,sizeof length);
recv(newsock,buffer,sizeof buffer,0);
cout << buffer << endl;
}
if (newsock != -1)
{
close(newsock);
}
if (sock != -1)
{
close(sock);
}
}
int main()
{
server();
}
這不是你的問題的答案,但我會建議你使用Boost.Asio。 =) –
這就是純粹的C,除了單個'cout'語句。 – vines