一.前言
回顾之前进程间通信(无名管道,有名管道,消息队列,共享内存,信号,信号量),都是在同一主机由内核来完成的通信。
那不同主机间该怎么通信呢?
可以使用Socket编程来实现。
Socket编程可以通过网络来实现实现不同主机之间的通讯。
二.Socket编程的网络模型如下。
![Socket网络编程(TCP/IP)实现服务器/客户端通信。](https://imgs.yssmx.com/Uploads/2023/06/476015-1.png)
1.创建socket
创建通讯套接字
int socket(int domain, int type, int protocol);
//参数一:是通信时候用的协议族
// AF_UNIX, AF_LOCAL 用于本地进程/线程的网络通信
//AF_INET 用于IPV4的网络通信
//AF_INET6 用于IPV6的网络通信
//参数二:为sockt的类型
//SOCK_STREAM 流水式socket,对应的是TCP
//SOCK_DGRAM 数据报式socket 对应的是UDP
//参数三:通常填零
3.绑定socket/端口号
绑定IP地址端口号等。
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
//参数一:为创建socket返回的标识符
//参数二:为一个struct sockaddr *addr的指针结构体,里面包含了,IP地址和端口号,网络编程是一般使用的是struct sockaddr_in类型的。
// struct sockaddr_in
// {
// u_short sin_family; // 地址族, AF_INET
// u_short sin_port; // 端口号
// struct in_addr sin_addr; // IPV4地址
// char sin_zero[8]; // 8 bytes unused,作为填充
// };
//如果使用了struct sockaddr_in类型的,左后一定要强转成struct sockaddr *addr类型的。
//参数三:为大小,sizeof
4.监听端口号
函数原型如下
int listen(int sockfd, int backlog);
//参数一:为创建socket返回的文件描述符
//参数e二:为能
5.接受客户端的连接请求
程序运行后服务器会一直阻塞在这 等待客户端发送连接请求。
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
//参数一:为创建socket返回的文件描述符
//参数二:struct sockaddr类型的指针,用来存放端口号和IP地址
//参数三:为大小sizeof
6.请求服务器连接(客户端)
向服务器发送连接请求。
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
//参数一:为创建socket返回的文件描述符
//参数二:struct sockaddr类型的指针,用来存放端口号和IP地址
//参数三:为结构体大小
7.读取/写入
连接成功后开始信息的交互,可以使用循环,让交互不退出去
ssize_t read(int fd, void *buf, size_t count);
//参数一:文件描述符
//参数二:缓冲区
//参数san:读取的大小
ssize_t write(int fd, const void *buf, size_t count);
//参数与read出不多
8.关闭文件
通讯完毕,关闭文件
int close(int fd);
//参数:你要关闭哪个文件就写哪个文件的文件描述符
三.示例代码
1.server.c
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
int main(int argc,char *argv[])
{
struct sockaddr_in addr;
struct sockaddr_in addr2;
memset(&addr,0,sizeof(struct sockaddr_in));
memset(&addr2,0,sizeof(struct sockaddr_in));
char *readbuf = (char *)malloc(sizeof(struct sockaddr_in)*10);
char mas[128] ={0};
int cockfd;
int sockfd;
int nread;
if(argc != 3)//判断输入的参数是否等于3
{
printf("param not good\n");
exit(-1);
}
if(sockfd = socket(AF_INET,SOCK_STREAM,0) == -1)//创建Socket,使用IPV4,TCP类型
{
printf("creat socket faild\n");
}
addr.sin_family = AF_INET; // 地址族, AF_INET,2 bytes
addr.sin_port = htons(atoi(argv[2])); // 端口,2 bytes
inet_aton(argv[1],&addr.sin_addr);//使用inet_aton函数将IP地址转换为网络序列。
bind(sockfd,(struct sockaddr*)&addr,sizeof(sockaddr_in));
listen(sockfd,10);//监听
while(1)
{
//尝试连接
cockfd = accept(sockfd,(struct sockaddr*)&addr2,sizeof(sockaddr_in));
if(cockfd == -1)
{
perror("why");//失败打印原因。
}
printf("get conset : %s\n",inet_nota(addr2.sin_addr));//打印连接成功的IP地址
//创建进程,让同时维护,读和写
if(fork() == 0)
{
while(1)
{
memset(readbuf,0,malloc_usable_size(readbuf))//每次通讯完成,内容置为0
nread = read(cockfd,readbuf,malloc_usable_size(readbuf));//读取信息
printf(" get message : %s\n",readbuf);//输出读取的内容
}
if(fork() == 0)子进程在创建一个子进程让同时运行读和写
{
while(1)
{
memset(msg,0,sizeof(msg));//每次运行前把数组初始化
printf("please input\n");
gets(msg);//获取信息
write(cockfd,msg,strlen(msg));写入信息
}
}
}
}
return 0;
}
示例代码
2.client.c文章来源:https://www.toymoban.com/news/detail-476015.html
#include<stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
int main(int argc,char *argv[])
{
struct sockaddr_in addr;
memset(&addr,0,sizeof(struct sockaddr_in));
char *readbuf = (char *)malloc(sizeof(struct sockaddr_in)*10);
char mas[128] ={0};
int cockfd;
int sockfd;
int nread;
if(argc != 3)
{
printf("param not good\n");
exit(-1);
}
ifcockfd = socket(AF_INET,SOCK_STREAM,0) == -1)
{
printf("creat socket faild\n");
}
addr.sin_family = AF_INET; // 地址族, AF_INET,2 bytes
addr.sin_port = htons(atoi(argv[2])); // 端口,2 bytes
inet_aton(argv[1],&addr.sin_addr);//使用inet_aton函数将IP地址转换为网络序列。
connect(cockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr));//请求连接
while(1)/
{
if(fork() == 0)//创建进程,同时维护读写
{
while(1)
{
memset(readbuf,0,malloc_usable_size(readbuf))
nread = read(cockfd,readbuf,malloc_usable_size(readbuf));//读取内容
printf(" get message : %s\n",readbuf);//打印读取到的内容
}
if(fork() == 0)
{
while(1)
{
memset(msg,0,sizeof(msg));
printf("please input\n");
gets(msg); //获取信息
write(cockfd,msg,strlen(msg));//写入信息
}
}
}
}
return 0;
}
以上就是我这段时间以来对网络编程的学习和理解,顺便记录一下,希望对你们会有所帮助,如果有不对的地方,欢迎大家来指导,谢谢!文章来源地址https://www.toymoban.com/news/detail-476015.html
到了这里,关于Socket网络编程(TCP/IP)实现服务器/客户端通信。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!