套接字相关函数socket()、bind()、listen()、connect()、accept()、recv()、send()、select()、close()
https://blog.csdn.net/weixin_45525272/article/details/107732407
atoi
atoi (表示 ascii to integer)是把字符串转换成整型数的一个函数,应用在计算机程序和办公软件中。int atoi(const char *nptr)
函数会扫描参数 nptr字符串,会跳过前面的空白字符(例如空格,tab缩进)等。如果 nptr不能转换成 int 或者 nptr为空字符串,那么将返回 0 。特别注意,该函数要求被转换的字符串是按十进制数理解的。atoi输入的字符串对应数字存在大小限制(与int类型大小有关),若其过大可能报错-1。
htons
htons是将整型变量从主机字节顺序转变成网络字节顺序, 就是整数在地址空间存储方式变为高位字节存放在内存的低地址处。
bzero()函数
原型:extern void bzero(void *s, int n
);
参数说明:s 要置零的数据的起始地址;
n 要置零的数据字节个数。
用法:#include <string.h>
功能:置字节字符串s的前n个字节为零且包括‘\0’。
说明:bzero无返回值,并且使用string.h头文件,string.h曾经是posix标准的一部分,但是在POSIX.1-2001标准里面,这些函数被标记为了遗留函数而不推荐使用。在POSIX.1-2008标准里已经没有这些函数了。推荐使用memset替代bzero。
服务器
/*************************************************************************
> File Name: server.c
> Author: 杨永利
> Mail: 1795018360@qq.com
> Created Time: 2020年08月01日 星期六 09时57分56秒
************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <strings.h>
int main(int argc, char* argv[]){
if(argc != 2){
printf("use this main with prot\n");
exit(1);
}
//第一步,创建一个服务器套接字描述附
//AF_INET是地址族,PF_INET是协议族
//创建服务器需要与陌生的客户端进行链接,所以不能选择地址族
int server_socket = socket(PF_INET, SOCK_STREAM, 0);
if(server_socket == -1){
//创建套接字失败
printf("socket() error!\n");
exit(-1);
}
//第二步,创建一个服务器地址结构体,用来与套接字绑定并且监听这个地址上的所有访问
struct sockaddr_in server_addr;
//清空结构体或者类型
//第一个参数为结构体或者类型的指针,第二个参数为你希望清空到多少个字节
//第三个参数为这个结构体或者类型的字节大小
memset(&server_addr, 0, sizeof(server_addr));
//服务器的地址结构体也需要设置为地址族
server_addr.sin_family = AF_INET;
//端口号,我们选择动态端口号,为了方便更改端口号,以免端口号被占用
server_addr.sin_port = htons(atoi(argv[1]));
//INADDR_ANY就是指定地址为0.0.0.0的地址,这个地址事实上表示不确定地址,或“所有地址”、“任意地址”。 一般来说,在各个系统中均定义成为0值。
server_addr.sin_addr.s_addr = INADDR_ANY;
//第三步,绑定套接字和地址结构体
//第一个参数为需要绑定的网络通信套接字描述符
//第二个参数为(struct sockaddr*)类型,但是我们创建地址都是使用sockaddr_in类型,所以需要进行一次类型的强制转换
//第三个参数,需要我们传递结构体的大小
//bind()返回值成功为0
//失败返回-1
//if对数字的判断是(是否为0值)
//0值为false 非0值为true
//C/C++不相信bool值,更相信0和非0
if(bind(server_socket, (struct sockaddr*)&server_addr, sizeof server_addr)){
printf("bind() error!\n");
exit(-1);
}
//第四步,监听套接字
if(listen(server_socket, 5)){
printf("listen() error!\n");
exit(-1);
}
//第五步,创建一个套接字用来接收新的客户端连接
//使用accept()去等待新的客户端的连接
//第一个参数是我们的服务器套接字
//第二个参数为sockaddr*类型的指针(可选)
//第三个参数为sockaddr*结构体的大小(可选)
int client_socket;
while(1){
//接收新的客户端访问的网络套接字描述符
if((client_socket = accept(server_socket, NULL, NULL)) < 0){
printf("accept() error!\n");
exit(1);
}
printf("有新的客户端连接了,他的套接字是%d\n", client_socket);
char message[1024];
while(1){
//第六步
bzero(message, sizeof(message));
int read_len;
if((read_len = read(client_socket, message, sizeof(message))) < 0){
printf("read() error \n");
exit(-1);
}
if(!read_len){
printf("客户端推出了聊天\n");
break;
}
printf("客户端说:%s\n", message);
//第七步,与客户端通信
int w_len = write(client_socket, message, strlen(message));
if(w_len != strlen(message)){
printf("write() error!\n");
exit(-1);
}
}
}
//第八步
close(client_socket);
close(server_socket);
return 0;
}
客户端
/*************************************************************************
> File Name: client.c
> Author: 杨永利
> Mail: 1795018360@qq.com
> Created Time: 2020年08月01日 星期六 10时01分47秒
************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <strings.h>
int main(int argc, char* argv[]){
if (argc != 3)
{
printf("参数错误!\n");
return -1;
}
// 第一步创建网络通信套接字描述符
int client_socket=socket(AF_INET,SOCK_STREAM,0);
// 第二步创建服务器的地址结构体
struct sockaddr_in server_addr;
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(atoi(argv[2]));
server_addr.sin_addr.s_addr=inet_addr(argv[1]);
// 第三步 连接服务器
if (connect(client_socket,(struct sockaddr*)&server_addr,sizeof(server_addr))==-1)
{
/* code */
printf("连接服务器失败!\n");
return -1;
}
printf("连接服务器成功!\n");
char message[1024];
bzero(message,sizeof(message));
char buf[1024];
printf("我是客户端,我将给服务器发送内容\n");
printf("如果希望聊天退出,请输入q或者Q:\n");
while(1)
{
printf("我发送给服务器的:\n");
scanf("%s",buf);
if (strlen(buf)==1)
{
if(buf[0] == 'q' || buf[0] == 'Q')
break;
}
if(strlen(buf) != write(client_socket, buf, strlen(buf))){
printf("write() error!\n");
exit(-1);
}
if(read(client_socket, message, sizeof(message)) <= 0){
printf("read() error!\n");
return -1;
}
printf("服务器对我说:%s\n", message);
bzero(buf, sizeof(buf));
bzero(message, sizeof(message));
}
close(client_socket);
printf("服务器关闭了!\n");
return 0;
}