C语言socket TCP/IP通讯Server/Client程序(Ubuntu Linux 24.04环境)

上篇文章介绍了Ubuntu Linux 24.04 C语言TCP/IP socket编程基础知识,本文将用C语言在Ubuntu Linux 24.04环境下开发一对使用socket进行TCP/IP通讯的Server/Client程序,实现的功能是:

1. 当client连上server时,显示连接成功的信息,然后等待client的输入。

2. 将client的输入在server端显示。

socket_server.c文件的内容如下:

/*
编译生成可执行程序(Ubuntu Linux 24.04)
# gcc ./socket_server.c -o socket_server
# ./socket_server

查看防火墙的状态:(国内的云服务器80,443,8080,8443是备案端口,必须备案以后才能从外网访问,注意避免使用)
# ufw status
# ufw allow 8888
查看端口是否被其它程序占用
# sudo apt lsof
# lsof -i:8888
*/

#include <stdio.h>      // printf
#include <string.h>	    // strlen(char*)
#include <unistd.h>     // close(int file_descriptor): close socket
#include <sys/socket.h> // socket(), bind(), accept(), etc
#include <netdb.h>      // gethostbyname(char* domain_name)
#include <arpa/inet.h>	// long inet_addr(char* ip_address) : convert ip string to long int format

#define SERVER_LISTEN_PORT 8888
#define SOCK_BUF_SIZE 10241
#define SOCK_BUF_SIZE1 10240 // subtract 1 for the null terminator at the buf end
#define SOCK_CONN_QUEUE_MAX 3


int main(int argc, char * argv[])
{
	int r=0;

	int listen_sock, sock;
	struct sockaddr_in server_addr, client_addr;
	socklen_t addrlen = sizeof(struct sockaddr_in);

  int client_count=0;	char *client_ip; int client_port;

	char buffer[SOCK_BUF_SIZE] = { 0 };
	long recv_size=0, send_size=0;

	if ((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("create server listen socket failed"); goto fail; 	}
	printf("create server listen socket succeed\n");

	server_addr.sin_family = AF_INET; // IPv4
	server_addr.sin_addr.s_addr = INADDR_ANY;	// 监听所有本地IP地址
	server_addr.sin_port = htons(SERVER_LISTEN_PORT);
	if (bind(listen_sock, (struct sockaddr*)&server_addr, addrlen) == -1) { perror("server listen socket bind to ip:port failed"); goto fail_close; }
	printf("bind server listen socket to port %d succeed\n", SERVER_LISTEN_PORT);

	if (listen(listen_sock, SOCK_CONN_QUEUE_MAX) == -1) { perror("server socket start listening failed"); goto fail_close; }
	printf("server socket starts listening ...\n");

	while((sock	= accept(listen_sock, (struct sockaddr*)&client_addr,	&addrlen)) > 0)
	{			
		client_count++;
		client_ip = inet_ntoa(client_addr.sin_addr); client_port = ntohs(client_addr.sin_port);
		printf("%d --------------- \nserver socket accepted a client connection:  %s:%d ---------------\n", client_count, client_ip, client_port);
		// if(set_socket_options(sock) == -1) goto end_close_client;
		while((recv_size = recv(sock, buffer, SOCK_BUF_SIZE1, 0))>0)
		{
			if(recv_size<0) { printf("receive from client failed\n"); goto end_close_client;}
			buffer[recv_size]=0; // set string end
			printf("received %ld bytes data: \n%s\n", recv_size, buffer);
		}
		//send_size = send(sock, hello, strlen(hello), 0); if(send_size<0) { printf("write to client failed\n"); goto end_close_client;}
		//printf("Hello message sent\n");
		end_close_client: close(sock);
		printf("waiting for next client ...\n");
	}

	close(listen_sock); goto succeed;
	fail_close: close(listen_sock); goto fail;
	succeed: return r;
	fail: r=1; return r;
}

socket_client.c文件的内容如下:

/*
编译生成可执行程序(Ubuntu Linux 24.04)
# gcc ./socket_client.c -o socket_client
# ./socket_client
*/

#include <stdio.h>      // printf
#include <string.h>	    // strlen(char*)
#include <stdlib.h>     // free(*memory)
#include <unistd.h>     // close(int file_descriptor): close socket
#include <sys/socket.h> // socket(), bind(), accept(), etc
#include <netdb.h>      // gethostbyname(char* domain_name)
#include <arpa/inet.h>	// long inet_addr(char* ip_address) : convert ip string to long int format

#define SERVER_LISTEN_PORT 8888
#define SOCK_BUF_SIZE 10241
#define SOCK_BUF_SIZE1 10240 // subtract 1 for the null terminator at the buf end
#define SERVER_DOMAIN_NAME "idealand.space"
#define BUDA_F(p) if(p){ free(p); p=NULL; } 


/* 通过域名获取socket可用的ip地址格式,用于连接server socket 
   hostname: 例如 idealand.space */
struct in_addr * get_sock_addr(char *hostname)
{
	printf("resolving %s to IP address...\n" , hostname);
	struct hostent *he;
	struct in_addr **addr_list; // data in struct in_addr is long int ip
	int i;
		
	if ( (he = gethostbyname( hostname ) ) == NULL )  goto fail;
	
	addr_list = (struct in_addr **) he->h_addr_list;
	struct in_addr * ip_addr=NULL;	
	for(i = 0; (ip_addr=addr_list[i]) != NULL; i++) 
	{
		printf("%d: %s\n", i+1 , inet_ntoa(*ip_addr) ); // inet_ntoa convert an IP address in long int format to dotted format
		goto succeed; // use the first IP address 
	}	
	if(ip_addr==NULL) goto fail;

	succeed: return ip_addr;
	fail: printf("gethostbyname for %s failed", hostname); return NULL;
}

int main(int argc, char * argv[])
{
	int r=0;

	struct in_addr * ip_addr=get_sock_addr(SERVER_DOMAIN_NAME);
	if(ip_addr==NULL) goto fail;

	struct sockaddr_in server_addr;
	server_addr.sin_family = AF_INET; // IPv4
	server_addr.sin_addr = *ip_addr;	
	server_addr.sin_port = htons(SERVER_LISTEN_PORT);
	socklen_t addrlen = sizeof(struct sockaddr_in);

	int sock;
	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("create client socket failed\n"); goto fail; 	}
	printf("create client socket succeed\n");

	if (connect(sock , (struct sockaddr *)&server_addr , addrlen) == -1) { perror("connect to server failed\n"); goto fail_close; }
	printf("connect to server succeed\n");

	char *line = NULL; size_t len = 0; ssize_t read;
	while((read = getline(&line, &len, stdin)) > 0)
	{			
		if(send(sock, line, read,	0) <= 0) goto fail_close;
		BUDA_F(line);
	}
	BUDA_F(line);

	close(sock); goto succeed;
	fail_close: close(sock); goto fail;
	succeed: return r;
	fail: r=1; return r;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
为了在Windows系统中与Ubuntu系统中的ROS进行通信,可以使用ROS的TCP/IP协议栈。下面是实现ROS Windows TCP通信的步骤: 1. 在Windows系统中安装ROS,可以使用ROS的Windows版本或者使用虚拟机在Windows系统中运行Ubuntu系统。 2. 在Windows系统中安装ROS的TCP/IP协议栈,可以使用ROS的roscpp库中的TCP/IP协议栈或者使用第三方库,例如Boost.Asio。 3. 在Windows系统中编写TCP/IP Client程序,连接到Ubuntu系统中的ROS TCP/IP Server。 4. 在Windows系统中发送数据到Ubuntu系统中的ROS TCP/IP Server,可以使用ROS的roscpp库中的TCP/IP协议栈提供的接口。 5. 在Ubuntu系统中编写TCP/IP Server程序,接收来自Windows系统的数据,并将其转发给ROS系统中的其他节点。 6. 在Ubuntu系统中使用ROS的roscpp库中的TCP/IP协议栈提供的接口,将接收到的数据转发给ROS系统中的其他节点。 下面是一个简单的ROS Windows TCP通信的例子: ```cpp // Windows TCP/IP Client程序 #include <ros/ros.h> #include <ros/network.h> #include <boost/asio.hpp> int main(int argc, char **argv) { ros::init(argc, argv, "ros_tcp_client"); ros::NodeHandle nh; boost::asio::io_service io_service; boost::asio::ip::tcp::socket socket(io_service); boost::asio::ip::tcp::resolver resolver(io_service); boost::asio::connect(socket, resolver.resolve({"192.168.1.100", "12345"})); // 连接到Ubuntu系统中的ROS TCP/IP Server std::string message = "Hello, ROS!"; boost::asio::write(socket, boost::asio::buffer(message)); // 发送数据到Ubuntu系统中的ROS TCP/IP Server return 0; } // Ubuntu ROS TCP/IP Server程序 #include <ros/ros.h> #include <ros/network.h> #include <boost/asio.hpp> void handle_accept(boost::asio::ip::tcp::socket socket, ros::Publisher pub) { boost::asio::streambuf buffer; boost::asio::read_until(socket, buffer, "\n"); // 接收来自Windows系统的数据 std::istream is(&buffer); std::string message; std::getline(is, message); pub.publish(message); // 将接收到的数据转发给ROS系统中的其他节点 } int main(int argc, char **argv) { ros::init(argc, argv, "ros_tcp_server"); ros::NodeHandle nh; ros::Publisher pub = nh.advertise<std::string>("ros_tcp_data", 1000); boost::asio::io_service io_service; boost::asio::ip::tcp::acceptor acceptor(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 12345)); while (ros::ok()) { boost::asio::ip::tcp::socket socket(io_service); acceptor.accept(socket); handle_accept(std::move(socket), pub); } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qiuzen

您的资助将帮助我创作更好的作品

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值