1.安装ubuntu的几种方式
方法一:VMWARE安装虚拟机,通过官网下载IOS镜像,通过镜像安装虚拟机
方法二(推荐):如果是windows系统,建议可以装双系统,准备U盘下载UBUNTU镜像,通过U盘安装UBUNTU
若使用第一种方式安装则需要进行网络配置,第二种方式则忽略
修改/etc/netplan/00-installer-config.yaml文件,若不存在则可以通过sudo nano来创建并编辑新文件,加入如下内容
network:
ethernets:
ens33:
dhcp4: true
version: 2
应用配置:sudo netplan apply
修改/etc/network/interfaces
auto lo
iface lo inet loopback
auto ens33
iface ens33 inet dhcp
重启网络:systemctl restart NetworkManager
2.安装VMtools
sudo apt-get update
sudo apt-get install open-vm-tools-desktop
附UBUNTU22.04阿里云镜像源
修改以下文件添加镜像源
sudo nano /etc/apt/source.list
deb https://mirrors.aliyun.com/debian/ bullseye main non-free contrib
deb-src https://mirrors.aliyun.com/debian/ bullseye main non-free contrib
deb https://mirrors.aliyun.com/debian-security/ bullseye-security main
deb-src https://mirrors.aliyun.com/debian-security/ bullseye-security main
deb https://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib
deb-src https://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib
deb https://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib
deb-src https://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib
3.安装Docker
①添加软件源密钥:curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
②
添加docker软件源:
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/debian \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
③sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
4.编写Dockerfile
sudo nano Dockerfile
FROM gcc:4.9
COPY server.c /usr/src/app/
WORKDIR /usr/src/app
RUN gcc server.c -o server -pthread
CMD ["./server"]
5.编写server.c和client.c
server.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
void *send_data(void *arg)
{
int connfd = *(int*)arg;
char s[64] = {0};
while(1)
{
fgets(s, 64, stdin);
s[strlen(s)-1] = '\0';
write(connfd, s, 64);
memset(s, 0, 64);
}
}
int main(int argc, char *argv[])
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
{
perror("socket");
return -1;
}
//端口复用函数
int on = 1;
int k = setsockopt(sockfd, SOL_SOCKET,SO_REUSEADDR, &on, sizeof(on));
if(k == -1)
{
perror("setsockopt");
return -1;
}
struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(8090);
ser.sin_addr.s_addr = inet_addr("172.17.0.2");
int ret = bind(sockfd, (struct sockaddr *)&ser, sizeof(ser));
if(ret == 0)
{
printf("绑定成功\n");
}
else
{
perror("bind");
return -1;
}
ret = listen(sockfd, 5);
if(ret == 0)
{
printf("监听成功\n");
}
else
{
perror("listen");
return -1;
}
struct sockaddr_in client;
int n = sizeof(client);
int connfd;
while(1)
{
connfd = accept(sockfd, (struct sockaddr *)&client, &n);
if(connfd == -1)
{
perror("accept");
return -1;
}
else
{
printf("连接成功\n");
}
printf("client ip:%s\nclient port:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
pthread_t pid;
pthread_create(&pid, NULL, send_data, (void *)&connfd);
pthread_detach(pid);
while(1)
{
char buf[64] = {0};
ret = read(connfd, buf, 64);
if(ret < 0)
{
perror("read");
return -1;
}
else if(ret == 0)
{
close(connfd);
break;
}
printf(">>:%s\n", buf);
if(strcmp(buf, "time") == 0)
{
time_t now = time(NULL);
char *p = ctime(&now);
char data[64];
strcpy(data, p);
write(connfd, data, strlen(data));
memset(buf, 0, 64);
memset(data, 0, 64);
}
else if(strncmp(buf, "get", 3) == 0)
{
int i, j = 0;
char str[64] = {0};
for(i = 4; i <= strlen(buf)-1; i++)
{
str[j] = buf[i];
j++;
}
memset(buf, 0, 64);
int fd = open(str, O_RDONLY);
while((ret = read(fd, buf, 64)) != 0)
{
write(connfd, buf, ret);
memset(buf, 0, 64);
}
write(connfd, "over", 64);
memset(buf, 0, 64);
memset(str, 0, 64);
close(fd);
}
else
{
char arr[64];
sprintf(arr, "%ld", strlen(buf));
write(connfd, arr, strlen(arr));
memset(buf, 0, 64);
memset(arr, 0, 64);
}
}
}
close(sockfd);
return 0;
}
client.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
void *recv_data(void *arg)
{
int sockfd = *(int *)arg;
char s[64] = {0};
while(1)
{
int ret = read(sockfd, s, 64);
if(ret < 0)
{
perror("read");
return NULL;
}
printf("%s\n", s);
memset(s, 0, 64);
}
}
int main(int argc, char *argv[])
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1)
{
perror("socket");
return -1;
}
pthread_t pid;
pthread_create(&pid, NULL, recv_data, (void *)&sockfd);
pthread_detach(pid);
struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(8090);
//ser.sin_addr.s_addr = inet_addr("主机网络地址");
ser.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = connect(sockfd, (struct sockaddr *)&ser, sizeof(ser));
if(ret == -1)
{
perror("connect");
return -1;
}
char buf[64];
while(1)
{
fgets(buf, 64, stdin);
buf[strlen(buf)-1] = '\0';
write(sockfd, buf, 64);
if(strcmp(buf, "time") == 0)
{
char data[64];
read(sockfd, data, 64);
printf(">>:%s\n", data);
memset(buf, 0, 64);
memset(data, 0, 64);
}
else if(strncmp(buf, "get", 3) == 0)
{
char str[64];
while(read(sockfd, str, 64) != 0)
{
if(strcmp(str, "over") == 0)
{
memset(str, 0, 64);
break;
}
printf(">>:%s\n", str);
memset(buf, 0, 64);
memset(str, 0, 64);
}
}
else
{ char arr[64] = {0};
read(sockfd, arr, 64);
printf(">>:%s\n", arr);
memset(buf, 0, 64);
memset(arr, 0, 64);
}
}
close(sockfd);
return 0;
}
注意服务端IP地址一般为Docker的虚拟地址,若要实现多机通信,客户端连接的是虚拟机或者主机的地址,不是Docker虚拟地址
执行命令:docker build -it tcp:first
则会生成一个名为tcp:first的镜像,可通过docker images 查看
执行命令:docker run -p 8090:8050 -it --name test tcp:first
通过上述命令会使得服务端在容器中运行
在另一台主机上通过gcc client.c -o client即可生成客户端可执行文件,执行可执行文件可得到如下结果
服务端端(手机拍的^.^):
客户端:
简单的tcp通信构建完成,server.c和client.c来源于TCP通信模型(C语言实现)_c语言实现tcp_昆工第一ikun的博客-CSDN博客
欢迎大家来讨论一起进步,如有错误之处请指出,谢谢