Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept and Connect on same port error #111

Open
MrRobertYuan opened this issue May 27, 2024 · 2 comments
Open

Accept and Connect on same port error #111

MrRobertYuan opened this issue May 27, 2024 · 2 comments
Assignees
Labels
bug Something isn't working

Comments

@MrRobertYuan
Copy link
Contributor

MrRobertYuan commented May 27, 2024

When testing Python, some tests use socket failed. The reason is:
when try to run a multi-thread code, which create a thread to accept on localhost:5555, and the other one connect to the same port, the connect one will continue to send message, but the accept one doesn't receive.

Change this question to a C code.
This code cannot work on RuxOS. Can replace this one to apps/c/httpserver, and run make ARCH=aarch64 A=apps/c/httpserver/ NET=y run to reproduce the problem.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
 
int client_num=0;//当前与服务器端连接的客户端的数目
#define PORT 5555			//目标地址端口号
#define ADDR "127.0.0.1" //目标地址IP
 
void* handle_client(void* arg){//参数与返回值都必须是void*类型(线程函数的特点)
	int len;//收到的字节数
	int* clnt_sock = (int*)arg;
	printf("a new client connected!!!!!,total %d client connected now\n",client_num);
    //向客户端发送数据
    char buff[100] = "hello I'm Server!!!\n";
    send(*clnt_sock, buff, sizeof(buff),0);
	//memset(buff,0,sizeof(buff));
	while(1){
		if((len=recv(*clnt_sock, buff, sizeof(buff),0))>0){
			if(strcmp(buff,"exit")==0){
				printf("client exit\n");
				break;
			}
			printf("receve from client:%s\n",buff);
			send(*clnt_sock, buff, sizeof(buff),0);
			memset(buff,0,sizeof(buff));
		}
		else{
			printf("client closed\n");
			break;
		}
	}
    //关闭套接字
    close(*clnt_sock);
	client_num--;
	printf("clnt_socket closed,remain total %d client connected now\n",client_num);
}

void* client(void* arg){
	int iSocketFD = 0; //socket句柄
	unsigned int iRemoteAddr = 0;
	struct sockaddr_in stRemoteAddr = {0}; //对端,即目标地址信息
	socklen_t socklen = 0;  	
	char buf[4096] = {0}; //存储接收到的数据
 
	iSocketFD = socket(AF_INET, SOCK_STREAM, 0); //建立socket
	if(0 > iSocketFD)
	{
		printf("创建socket失败!\n");
		return 0;
	}	
 
	stRemoteAddr.sin_family = AF_INET;
	stRemoteAddr.sin_port = htons(PORT);
	inet_pton(AF_INET, ADDR, &iRemoteAddr);
	stRemoteAddr.sin_addr.s_addr=iRemoteAddr;
	
	//连接方法: 传入句柄,目标地址,和大小
	if(0 > connect(iSocketFD, (void *)&stRemoteAddr, sizeof(stRemoteAddr)))
	{
		printf("连接失败!\n");
		//printf("connect failed:%d",errno);//失败时也可打印errno
	}else{
		printf("连接成功!\n");
		recv(iSocketFD, buf, sizeof(buf), 0);
		printf("Received:%s\n", buf);
	}
	
	close(iSocketFD);//关闭socket
	return NULL;
}

int main(){
	pthread_t tidp;//线程的id
 
    //创建套接字
    int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	printf("create socket success!\n");
    //将套接字和IP、端口绑定
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
    serv_addr.sin_family = AF_INET;  //使用IPv4地址
    unsigned int tmpAddr = 0;
    inet_pton(AF_INET, ADDR, &tmpAddr);
	serv_addr.sin_addr.s_addr=tmpAddr;
    //serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
    serv_addr.sin_port = htons(5555);  //端口
    bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
	printf("bind success!!\n");
    //进入监听状态,等待用户发起请求
    listen(serv_sock, 3);
	printf("listening......\n");
    //接收客户端请求
    struct sockaddr_in clnt_addr;
    socklen_t clnt_addr_size = sizeof(clnt_addr);
	
	pthread_t clientp;
	if(pthread_create(&clientp, NULL, client, NULL) == -1){
		printf("create client error!");
	}
	else{
		printf("create client success!");
	}
    while(1){
        int* clnt_sock = (int *)malloc(sizeof(int));
		*clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
		pthread_t clientp;
		if(pthread_create(&clientp, NULL, client, NULL) == -1){
			printf("create client error!");
		}
		else{
			printf("create client success!");
		}
		
		if((pthread_create(&tidp, NULL, handle_client, (void*)clnt_sock)) == -1){//客户端来一个请求就创建一个线程
			printf("create error!\n");
		}
		else{
			printf("create success!\n");
			client_num++;
		}
    }
	
    close(serv_sock);//关闭服务器端
    return 0;
}
@coolyjg coolyjg added the bug Something isn't working label May 29, 2024
@lhw2002426
Copy link
Contributor

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define PORT 5555
#define BUFFER_SIZE 1024

void *server_thread(void *arg) {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    char buffer[BUFFER_SIZE] = {0};

    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("Socket failed");
        exit(EXIT_FAILURE);
    }

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("Bind failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    if (listen(server_fd, 3) < 0) {
        perror("Listen failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    printf("Server listening on 127.0.0.1:%d\n", PORT);

    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
        perror("Accept failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    read(new_socket, buffer, BUFFER_SIZE);
    printf("Server received: %s\n", buffer);
    send(new_socket, "Hello from server", strlen("Hello from server"), 0);

    close(new_socket);
    close(server_fd);

    return NULL;
}

void *client_thread(void *arg) {
    sleep(1); // Ensure the server is listening before the client tries to connect

    struct sockaddr_in serv_addr;
    char *message = "Hello from client";
    char buffer[BUFFER_SIZE] = {0};
    int sock = 0;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket creation error");
        return NULL;
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
        perror("Invalid address / Address not supported");
        close(sock);
        return NULL;
    }

    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        perror("Connection failed");
        close(sock);
        return NULL;
    }

    send(sock, message, strlen(message), 0);
    printf("Client sent: %s\n", message);
    read(sock, buffer, BUFFER_SIZE);
    printf("Client received: %s\n", buffer);

    close(sock);

    return NULL;
}

int main() {
    pthread_t server_tid, client_tid;

    if (pthread_create(&server_tid, NULL, server_thread, NULL) != 0) {
        perror("Failed to create server thread");
        exit(EXIT_FAILURE);
    }

    if (pthread_create(&client_tid, NULL, client_thread, NULL) != 0) {
        perror("Failed to create client thread");
        exit(EXIT_FAILURE);
    }

    pthread_join(server_tid, NULL);
    pthread_join(client_tid, NULL);

    return 0;
}

this code is also connect to localhost in same port, but it could run correctly , I don't konw why

@coolyjg
Copy link
Contributor

coolyjg commented Jun 13, 2024

Server address should bind at INADDR_ANY

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants