c - C Socket 服务器未捕获传入连接
问题描述
如标题所示,我在 Linux 上有一个带有服务器和客户端的 C TCP 套接字应用程序。服务器正在 localhost 地址 127.9.0.1 的端口 28000 上侦听连接。有时,客户端“打印一个连接语句”,所以 connect() 已经完成。这让我觉得服务器接受了连接请求。但是,客户端“连接”并在从服务器接收到的第一个数据时“冻结”。但实际上服务器还没有准备好发送数据,所以客户端保持在那个状态。这是随机发生的,并且在重新编译后经常发生。我真的不知道问题出在哪里,因为这只发生在我的电脑上(尝试过本机 Linux、WSL 和 VM),我尝试在另一台电脑上执行并且发生的次数非常少。
我想澄清一下,这不会每次都发生,我让整个系统运行。地址绑定没问题,客户端的connect()和服务器的accept()都可以。例如,关闭电脑并启动,使连接工作。
代码很长(可能有一些错误)并且有一些非常糟糕的代码实践,请不要怪我:
服务器.c
#include "Client_List.h"
#define BACKLOG 10
typedef struct _t_args_comm
{
user* a;
user* b;
}COMMUNICATION;
bool debug = true;
int socket_ds;
clientNode *Clientlist;
void* ConnectionHandler(void*);
void getClientList(clientNode*, char**, int);
void desc_init(clientNode*, struct pollfd*);
void* Lobby();
void SIGINT_handler(int);
void ErrorServer(const char*, bool);
int main(int argc, char** argv)
{
if(argc == 2)
{
if(strcmp(argv[1], "true") == 0)
debug = true;
else
{
printf("Wrong parameter, Usage: ./server [true], exiting from the program\n");
exit(-1);
}
}
int res, connect_index, client_sock_ds;
socklen_t clientLength;
struct sockaddr_in serv_addr;
struct sockaddr_in client_addr;
char check[32];
pthread_t lobby_tid;
struct sigaction sig;
sigset_t set;
sigaddset(&set, SIGINT);
sig.sa_mask = set;
sig.sa_handler = SIGINT_handler;
// Opening a TCP socket using IP_V4
if((socket_ds = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
ErrorServer("socket open", true);
printf("[+] Server socket is created!\n");
// Setting up the sockaddr_in struct that will store server's address's informations
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT_NUMBER); // to byte order conversion;
// Binding ip address to the socket
if(inet_pton(AF_INET, "127.0.0.1", &(serv_addr.sin_addr)) <= 0)
ErrorServer("inet_pton()", true);
// Binding the server address to the socket
if(bind(socket_ds, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1)
ErrorServer("bind", true);
// Setting up backlog
if(listen(socket_ds, BACKLOG) == -1)
ErrorServer("listen", true);
printf("[+] Server is waiting for incoming connections...\n");
printf("-------------------------------------------------\n");
user tmpCli;
//Starting lobby's thread
if(pthread_create(&lobby_tid, NULL, Lobby, NULL) == -1)
ErrorServer("pthread_create()", true);
if(sigaction(SIGINT, &sig, NULL) == -1)
ErrorServer("changing SIGINT handler", false);
for(int i = 0; i < 2; ++i){
printf("Listening...\n");
while((client_sock_ds = accept(socket_ds, (struct sockaddr*)&client_addr, &clientLength)) == -1);
printf("[+] --------- New client connected ---------\n");
// Receiving username
do{
if((res =recv(client_sock_ds, tmpCli.username, (size_t)MAX_USERNAME_DIM, 0)) == -1)
ErrorServer("recv() username",true);
tmpCli.username[MAX_USERNAME_DIM-1] = '\0';
if(debug)
printf("username received : %s\n", tmpCli.username);
if(getClientByName(&Clientlist, tmpCli.username) != NULL){
printf("Username already taken\n");
strcpy(check, "there is");
}else{
printf("Valid username\n");
strcpy(check, "there isn't");
}
send(client_sock_ds, check, sizeof(check), 0);
}while(strcmp(check, "there is") == 0);
tmpCli.client_address = client_addr;
tmpCli.client_ds = client_sock_ds;
tmpCli.status = true;
insertClient(&Clientlist, tmpCli);
// Send new user struct to thread lobby to handle connection requests
}
// For the moment i'm handling connections here...
pthread_join(lobby_tid, NULL);
printf("I'am exiting!\n");
exit(0);
}
客户端.c
#include "Client_List.h"
void Talk(char *);
void *ThreadWorks(void * arg);
void SIGINT_handler();
bool debug = true;
bool quit = false;
int socket_ds;
int main(int argc, char** argv){
int res;
struct sockaddr_in serv_addr;
char check[32];
char buff[MAX_MSG_DIM];
char username[MAX_USERNAME_DIM];
char ipAddr[24];
char choose[MAX_USERNAME_DIM];
struct sigaction sig;
sigset_t set;
sigaddset(&set, SIGINT);
sigaddset(&set, SIGUSR1);
sig.sa_mask = set;
sig.sa_handler = SIGINT_handler;
// Opening a TCP socket using IP_V4
if((socket_ds = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
Error("socket()", true);
printf("[+] Client socket is created!\n");
/*
if(sigprocmask(SIG_UNBLOCK, &set, NULL) == -1)
Error("sigprocmask()", true);
*/
if(sigaction(SIGINT, &sig, NULL) == -1)
Error("sigaction() sigint", true);
if(sigaction(SIGUSR1, &sig, NULL) == -1)
Error("sigaction(), sigusr1", true);
// Setting up struct sockaddr
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT_NUMBER); // to network byte order conversion
if(inet_pton(AF_INET, "127.0.0.1", &(serv_addr.sin_addr)) <= 0) // Address of the server to connec
t to!
Error("inet_pton", true);
// binding the server address to the socket
do{
if((res = connect(socket_ds, (struct sockaddr*)&serv_addr, sizeof(serv_addr))) == -1)
Error("connect", false);
sleep(2);
}while(res != 0);
if(inet_ntop(AF_INET, &(serv_addr.sin_addr), ipAddr, 24) == NULL)
Error("inet_ntop", true);
printf("[+] Connected to the server with address %s\n", ipAddr);
// Sending username
do{
printf("[+] Insert your username: ");
scanf("%s", username);
send(socket_ds, username, MAX_USERNAME_DIM, 0);
if(recv(socket_ds, check, sizeof(check), 0) < 0)
printf("[-] Error during receiving data!\n");
if(strcmp(check, "there is") == 0)
printf("This username already exists!\n");
}while(strcmp(check, "there is") == 0);
printf("[+] Username accept!\n");
Client_List.h
客户端列表是一个包含链表实现的文件,并具有变量声明。这里只是变量部分:
/* Client_List.h*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/socket.h> // For socket things
#include <sys/unistd.h>
#include <netinet/ip.h> // For IPPROTO_xxxx
#include <netinet/in.h> // For bzero and sockaddr_in
#include <arpa/inet.h> // For inet_ntoa and inet_aton
#include <poll.h>
#define MAX_MSG_DIM 1024
#define MAX_USERNAME_DIM 64
#define MAX_USERS 30
#define PORT_NUMBER 28000
#define fflush(stdin) {while(getchar() != '\n');}
#define CONNECTION_REQUEST(usr) strcat("I want to connect to: " #usr);
#define ERR_USERNAME_TAKEN "This username is already been taken"
#define END_USERSLIST "END"
typedef struct us{
long client_ds;
struct sockaddr_in client_address;
char username[MAX_USERNAME_DIM];
bool status;
}user;
typedef struct clientNode{
user client;
int index;
struct clientNode *next;
}clientNode;
我只包括了连接部分以及我认为检查代码所需的一些东西,希望有人可以帮助我
感谢您的关注
解决方案
推荐阅读
- javascript - 页面加载后 PHP 回显语句为空白
- python - 将参数传递给 side_effect 函数以在 unittest.mock 中进行修补
- c - 在 C 宏中定义二维常量数组
- .net - 关联不同数据库中的两个实体以及两个应用程序之间的通信
- azure - 如何有条件地执行特定于 Azure SQL 托管实例的 SQL 代码?
- opengl - 如何在片段着色器中使用带有“返回”的多重采样?
- java - 访问远程应用服务器上的线程
- python-3.x - Python 请求 -+ 提琴手
- c# - 缩略图对象有 url,但没有内容
- python - 在python中的字符串格式中将十六进制剥离为单个数字