這是客戶端的一個朋友的代碼發給我的。我對套接字編程知之甚少。它意味着有點像聊天客戶端;發送文本到服務器和服務器將其發送到所有客戶端。我編輯它在哪裏顯示執行與聊天命令上的指令彩色文本。問題是/ ls命令將被識別並且暫時不會按照預期發送到服務器,但是如果聲明不會執行以外的任何其他指令。其次,使用命令或發送文本到服務器後,它不會讓我使用命令或發送文本了。我可以輸入,但沒有任何內容通過服務器,我也沒有收到典型的例如「接收到的字節12」消息;除了我使用/ dis命令從服務器斷開連接之外,當然我會說「Received Bytes -1」。任何想法或建議?提前致謝。C++ Linux多線程插座問題
我還在底部提供了服務器源,因爲有人認爲那裏存在問題。
客戶端源
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <netinet/in.h>
#include <resolv.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string>
#include <sstream>
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_GREEN "\x1b[32m"
#define ANSI_COLOR_YELLOW "\x1b[33m"
#define ANSI_COLOR_BLUE "\x1b[34m"
#define ANSI_COLOR_MAGENTA "\x1b[35m"
#define ANSI_COLOR_CYAN "\x1b[36m"
#define ANSI_COLOR_BRIGHT "\x1b[1m"
#define ANSI_COLOR_RESET "\x1b[0m"
using namespace std;
int main(int argv, char** argc){
string olr = "Global" ANSI_COLOR_RESET;
string help = ANSI_COLOR_CYAN "\n\n/help for a list of commands e.g help\n/ls to list online chat rooms e.g. /ls\n/j namehere to join a chat room. e.g. /j Global\n/p namehere -e codehere to private chat. e flag for encryption;\n\tnot required. e.g. /p Sunny got the dox?\n/tp to toggle receiving private messages or not e.g /tp\n/l codehere to listen for encrypted private messages. Seperate \n\tmultiple codes with a comma (,). e.g. /l 123,1234\n/st to stop listening for any encrypted messages e.g /st\n/c namehere to create a chat room. e.g. /c Journalism\n/clr to clear the screen e.g. /clr\n/dis to disconnect from the server e.g. /dis\n/con to connect to the server e.g. /con\n" ANSI_COLOR_RESET;
int host_port= 1604;
char* host_name="127.0.0.1";
struct sockaddr_in my_addr;
char buffer[1024];
int bytecount;
int buffer_len=0;
int hsock;
int * p_int;
int err;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if(hsock == -1){
printf("Error initializing socket %d\n",errno);
}
p_int = (int*)malloc(sizeof(int));
*p_int = 1;
if((setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1)||
(setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1)){
printf("Error setting options %d\n",errno);
free(p_int);
}
free(p_int);
my_addr.sin_family = AF_INET ;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = inet_addr(host_name);
if(connect(hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1){
if((err = errno) != EINPROGRESS){
fprintf(stderr, "Error connecting socket %d\n", errno);
}
}
printf(ANSI_COLOR_MAGENTA "\nOnline Rooms: ");
printf(olr.c_str());
printf(help.c_str());
//Now lets do the client related stuff
while (true){
buffer_len = 1024;
string pokemon;
pokemon = "/dis";
memset(buffer, '\0', buffer_len);
fgets(buffer, 1024, stdin);
buffer[strlen(buffer)-1]='\0';
stringstream ss;
string bufferstr;
ss << buffer;
ss >> bufferstr;
if (bufferstr == pokemon){
close(hsock);
}
else if (bufferstr == "/help"){
printf(help.c_str());
}
else if (bufferstr == "/ls"){
printf("Online Rooms: ");
printf(olr.c_str());
}
else if((bytecount=send(hsock, buffer, strlen(buffer),0))== -1){
fprintf(stderr, "Error sending data %d\n", errno);
}
//what happens after sent
//printf("Sent bytes %d\n", bytecount);
if((bytecount = recv(hsock, buffer, buffer_len, 0))== -1){
fprintf(stderr, "Error receiving data %d\n", errno);
}
printf("Recieved bytes %d\nReceived string \"%s\"\n", bytecount, buffer);
}
//close(hsock);
}
服務器源
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <netinet/in.h>
#include <resolv.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
void* SocketHandler(void*);
int main(int argv, char** argc){
int host_port= 1604;
struct sockaddr_in my_addr;
int hsock;
int * p_int ;
int err;
socklen_t addr_size = 0;
int* csock;
sockaddr_in sadr;
pthread_t thread_id=0;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if(hsock == -1){
printf("Error initializing socket %d\n", errno);
// goto FINISH;
}
p_int = (int*)malloc(sizeof(int));
*p_int = 1;
if((setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1)||
(setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1)){
printf("Error setting options %d\n", errno);
free(p_int);
// goto FINISH;
}
free(p_int);
my_addr.sin_family = AF_INET ;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = INADDR_ANY ;
if(bind(hsock, (sockaddr*)&my_addr, sizeof(my_addr)) == -1){
fprintf(stderr,"Error binding to socket, make sure nothing else is listening on this port %d\n",errno);
// goto FINISH;
}
if(listen(hsock, 10) == -1){
fprintf(stderr, "Error listening %d\n",errno);
// goto FINISH;
}
//Now lets do the server stuff
addr_size = sizeof(sockaddr_in);
while(true){
printf("waiting for a connection\n");
csock = (int*)malloc(sizeof(int));
if((*csock = accept(hsock, (sockaddr*)&sadr, &addr_size))!= -1){
printf("---------------------\nReceived connection from %s\n",inet_ntoa(sadr.sin_addr));
pthread_create(&thread_id,0,&SocketHandler, (void*)csock);
pthread_detach(thread_id);
}
else{
fprintf(stderr, "Error accepting %d\n", errno);
}
}
FINISH:
;
}
void* SocketHandler(void* lp){
int *csock = (int*)lp;
char buffer[1024];
char pokemon[3];
int buffer_len = 1024;
int bytecount;
int ignore;
pokemon[0] = '/';
if (buffer[0] == pokemon[0]){
ignore = 1;
} else {ignore = 0;}
memset(buffer, 0, buffer_len);
if((bytecount = recv(*csock, buffer, buffer_len, 0))== -1){
fprintf(stderr, "Error receiving data %d\n", errno);
//goto FINISH;
}
printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer);
strcat(buffer, " SERVER ECHO");
if (ignore==0) {
if((bytecount = send(*csock, buffer, strlen(buffer), 0))== -1){
fprintf(stderr, "Error sending data %d\n", errno);
// goto FINISH;
}
}
printf("Sent bytes %d\n", bytecount);
//FINISH:
// free(csock);
//return 0;
}
瞭解更多關於[poll(2)](http://man7.org/linux/man-pages/man2/poll.2.html)和[事件循環](http://en.wikipedia.org /維基/ Event_loop)。另請參閱[高級Linux編程](http://advancedlinuxprogramming.com/)。使用'g ++ -Wall -g'(或* gcc -Wall -g'編譯* C *代碼)編譯。學習如何使用'gdb'調試器**。 –