主机(client)与ubuntu虚拟机(server)的通信(Version 1.0)
程序员文章站
2022-07-14 09:30:27
...
以下两个程序实现了ubuntu虚拟机 -> 主机VS2017的数据通信. 虽然实现了数据的通信, 但是有个问题值得我们注意: 当建立连接后, 我们在一段时间后关闭client程序(VS2017), 此时ubuntu端的send()函数会阻塞------这样一来, 每当我们在VS2017端关闭一次客户端程序, ubuntu端就会多一个浪费内存空间的服务端处理进程: 当VS2017端频繁开启关闭客户端程序, ubuntu端的压力会很大. 所以, 接下来如何应对客户端程序关闭变成了主要问题(应对方案将在Version 1.1中发布).
现在以下两个程序已经能够实现将ubuntu虚拟机端产生的数据送到主机VS 2017端.
//server.c 服务端
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <time.h>
#define SERVPORT 3333
#define BACKLOG 10
int random_number()//generating a random number
{
int a;
srand((unsigned)time(NULL));
a = rand();
return a;
}
int main()
{
int sockfd,client_fd;
int value;
int recvbytes;
int sin_size;
char buf[50];
struct sockaddr_in my_addr;
struct sockaddr_in remote_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);//建立socket --
my_addr.sin_family=AF_INET;//AF_INET地址族
my_addr.sin_port=htons(SERVPORT);//设定端口号(host -> networks)
my_addr.sin_addr.s_addr = INADDR_ANY;//32位IPv4地址
bzero(&(my_addr.sin_zero),8); //置前8个字节为0
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
{
perror("bind 出错!");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1) //监听socket连接,设置队列中最多拥有连接个数为10 --
{
perror("listen 出错!");
exit(1);
}
while(1)
{
sin_size = sizeof(struct sockaddr_in);//记录sockaddr_in结构体所占字节数
if ((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size)) == -1) //accept()缺省是阻塞函数,阻塞到有连接请求为止 --
{
perror("accept error");
continue;
}
printf("收到一个连接来自: %s\n", inet_ntoa(remote_addr.sin_addr));
if (!fork())
{
//test 1
//recv(client_fd, buf, 25, 0);
//printf("%s\n", buf);
//test 2
//send(client_fd, "12345", 5, 0);
//sending pieces of message to client
while(1)
{
//generating a random number and sending it to the host
value = random_number();
sprintf(buf, "%d", value);//int to string
//every one second client sends a random number converted to string to client
send(client_fd, buf, (int)strlen(buf), 0);
sleep(1);
}
close(client_fd);
exit(0);
}
close(client_fd);
}
}
//client 客户端 Visual Studio 2017 professional
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace data_receiving
{
class Program
{
public static Socket ClientSocket;
public static String IP = "192.168.239.132";//ubuntu虚拟机(server端)的IP地址
public static void receive_message()//接收ubuntu虚拟机发来的数据
{
int port = 3333;//通信端口
IPAddress ip = IPAddress.Parse(IP); //将IP地址字符串转换成IPAddress实例
ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//使用指定的地址簇协议、套接字类型和通信协议
IPEndPoint endPoint = new IPEndPoint(ip, port); // 用指定的ip和端口号初始化IPEndPoint实例
ClientSocket.Connect(endPoint); //与远程主机建立连接
//ClientSocket.Send(Encoding.ASCII.GetBytes("12345")); //测试PC -> Ubuntu的连通性
byte[] receive = new byte[100];
//ClientSocket.Receive(receive); //测试Ubuntu -> PC的连通性
//Console.WriteLine(Encoding.ASCII.GetString(receive));
while(true)
{
int length = ClientSocket.Receive(receive);
Thread.Sleep(1000);//程序休眠1s, 与server端保持同步
Console.WriteLine("接收消息为:" + Encoding.ASCII.GetString(receive));
}
ClientSocket.Close(); //关闭连接
}
static void Main(string[] args)//收到ubuntu虚拟机发来的数据, 并显示到终端
{
receive_message();
}
}
}
在ubuntu端运行服务端程序.
在主机端运行客户端程序.
回到服务端.