目录
一.创建一个socket文件夹用来存放编写的服务器端和客户端程序
二.编写服务器端代码
三.编写客户端代码
四.编译c语言程序
五.断开连接
六.可能涉及到的一些没接触过的知识点
一.创建一个socket文件夹用来存放编写的服务器端和客户端程序
(我系统里的文件在temp/socket$文件夹中)
二.编写服务器端代码
vim server.c
在server.c中编写的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>//提供IP地址转换函数int main()
{//1.创建监听的套接字int fd = socket(AF_INET,SOCK_STREAM, 0);if (fd == -1){perror("socket");//perror(s) 用来将上一个函数发生错误的原因输出到标准设备,参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。return -1;}//2.绑定本地的IP portstruct sockaddr_in saddr;saddr.sin_family = AF_INET;//地址族协议saddr.sin_port = htons(9999);//端口必须转换成大端saddr.sin_addr.s_addr = INADDR_ANY;//指定IP地址(INADDR_ANY泛指本机的意思,也就是表示本机的所有IP)int ret = bind(fd, (struct sockaddr*)&saddr, sizeof(saddr));if (ret == -1)//绑定失败 返回-1{perror("bind");return -1;}//3设置监听ret = listen(fd, 128);if (ret == -1){perror("listen");return -1;}//4阻塞并等待客户端的连接struct sockaddr_in caddr;int addrlen = sizeof(caddr);int cfd = accept(fd, (struct sockaddr*)&caddr,&addrlen );if (cfd == -1){perror("accept");return -1;}//连接建立成功,打印客户端的IP和端口信息char ip[32];printf("客户端的ip:%s,端口:%d\n",inet_ntop(AF_INET, &caddr.sin_addr.s_addr, ip, sizeof(ip)), ntohs(caddr.sin_port));//网络字节序转换为主机字节序//5.通信while (1){//接收数据char buff[1024];int len = recv(cfd, buff, sizeof(buff), 0);if (len > 0){printf("client say: %s\n", buff);send(cfd, buff, len, 0);}else if (len == 0){printf("客户端已经断开了连接...\n");break;}else{perror("recv");break;}}//关闭文件描述符close(fd);close(cfd);return 0;
}
三.编写客户端代码
vim client.c
在client中编写的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>//提供IP地址转换函数int main()
{//1.创建通信的套接字int fd = socket(AF_INET, SOCK_STREAM, 0);if (fd == -1){perror("socket");//perror(s) 用来将上一个函数发生错误的原因输出到标准设备,参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。return -1;}//2.连接服务器IP portstruct sockaddr_in saddr;saddr.sin_family = AF_INET;//地址族协议saddr.sin_port = htons(9999);//端口必须转换成大端inet_pton(AF_INET, "192.168.122.1 ", &saddr.sin_addr.s_addr);int ret = connect(fd, (struct sockaddr*)&saddr, sizeof(saddr));if (ret == -1)//连接失败 返回-1{perror("connect");return -1;}int number = 0;//3.通信while (1){//发送数据char buff[1024];sprintf(buff, "你好,hello ,world ,%d...\n", number++);send(fd, buff, strlen(buff) + 1, 0);//接收数据memset(buff, 0, sizeof(buff));int len = recv(fd, buff, sizeof(buff), 0);if (len > 0){printf("server say: %\n", buff);}else if (len == 0){printf("服务器端已经断开了连接...\n");break;}else{perror("recv");break;}sleep(1);}//关闭文件描述符close(fd);return 0;
}
四.编译c语言程序
[itliang@localhost socket]$ gcc client.c -o client
[itliang@localhost socket]$ gcc server.c -o server
运行server.c程序,先运行服务器端再运行客户端
运行client.c程序,至此客户端与服务器端建立通信,客户端收到服务器端消息,并输出“你好,hello,world”
服务器端收到客户端消息,并输出“你好,hello,world”
五.断开连接
当服务器端断开连接时,客户端会显示“服务器端已经断开了连接”
当客户端断开连接时,服务器端会显示“客户端已经断开了连接”
六.可能涉及到的一些没接触过的知识点
perror(s)函数
用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。
sockaddr_in在头文件#include<netinet/in.h>或#include <arpa/inet.h>
中定义,该结构体解决了sockaddr的缺陷,把port和addr 分开储存在两个变量中,如下:
GCC 是 Linux 下的编译工具集,是 GNU Compiler Collection 的缩写,包含 gcc、g++ 等编译器。这个工具集不仅包含编译器,还包含其他工具集,例如 ar、nm 等。
GCC 工具集不仅能编译 C/C++ 语言,其他例如 Objective-C、Pascal、Fortran、Java、Ada 等语言均能进行编译。GCC 在可以根据不同的硬件平台进行编译,即能进行交叉编译,在 A 平台上编译 B 平台的程序,支持常见的 X86、ARM、PowerPC、mips 等,以及 Linux、Windows 等软件平台。
有些纯净版的 Linux 默认没有 gcc 编译器,需要自己安装,在线安装步骤如下:
# 安装软件必须要有管理员权限
# ubuntu
$ sudo apt update # 更新本地的软件下载列表, 得到最新的下载地址
$ sudo apt install gcc g++ # 通过下载列表中提供的地址下载安装包, 并安装# centos
$ sudo yum update # 更新本地的软件下载列表, 得到最新的下载地址
$ sudo yum install gcc g++ # 通过下载列表中提供的地址下载安装包, 并安装
gcc 安装完毕之后,可以查看版本:# 查看 gcc 版本
$ gcc -v
$ gcc --version# 查看 g++ 版本
$ g++ -v
$ g++ --version
编译:
# 参数 -c 是进行文件的汇编, 汇编之前的两步会自动执行
$ gcc test.c -c -o app.o