在计算机网络中,Socket是一种实现网络通信的缺省方式,它是网络通信的接口,是我们进行数据交换和通信的基础。Socket通信在Linux系统中得到广泛应用,本文将从流程角度出发,图解Linux上Socket通信的整个过程。
成都创新互联坚持“要么做到,要么别承诺”的工作理念,服务领域包括:网站设计、成都做网站、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的独山网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!
一、什么是Socket
在计算机网络中,Socket是一种抽象概念,一种通信端口,是一个虚拟的门,是网络通信的接口。在Linux系统中,Socket是一种文件描述符,可以像操作文件一样读写,其中传输的数据源可以是文件、终端、网络等。
二、Socket通信的基本流程
Socket通信的基本流程图如下所示:
![Socket通信的基本流程](https://img-blog.csdnimg.cn/20231031192121364.png)
Socket通信的基本流程有以下几步:
1. 创建Socket:创建通信的Socket,用于接收和发送数据。
2. 绑定Socket:将Socket与本地IP地址和端口号绑定,确定Socket的具体使用位置。
3. 监听Socket:Socket处于监听状态,等待客户端的连接请求。
4. 接收连接:服务器端等待客户端的请求连接,一旦收到请求连接,就接受客户端的连接请求,并创建一个新的Socket进行通信。
5. 发送和接收数据:客户端和服务器端通过各自的Socket进行数据的发送和接收。
6. 关闭Socket:通信结束后,关闭Socket,释放资源。
现在,我们将详细解释每一步。
三、Socket通信的详细流程
1. 创建Socket
Socket创建通常使用socket()函数,该函数的原型为:
“`c
#include
// family表示使用的协议族,type表示Socket类型,protocol表示使用的协议,一般为0
int socket(int family, int type, int protocol);
“`
其中,family表示使用的协议族,type表示Socket类型,protocol表示使用的协议,一般为0。
常见的family有:
– AF_INET:IPv4协议族
– AF_INET6:IPv6协议族
常见的type有:
– SOCK_STREAM:基于TCP协议的流Socket,用于传输可靠的字节流数据
– SOCK_DGRAM:基于UDP协议的数据报Socket,用于传输无连接的、不可靠的数据
常见的protocol有:
– IPPROTO_IP:协议无关,通常为0
– IPPROTO_TCP:TCP协议,用于数据传输的可靠性
– IPPROTO_UDP:UDP协议,用于无连接的数据传输
2. 绑定Socket
绑定Socket通常使用bind()函数,该函数的原型为:
“`c
#include
// sockfd表示要绑定的Socket,addr表示本地IP地址和端口号,addrlen表示地址长度
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
“`
其中,sockfd表示要绑定的Socket,addr表示本地IP地址和端口号,addrlen表示地址长度。
绑定Socket的目的是为Socket确定一个具体的位置,指定Socket使用的本地IP地址和端口号。
3. 监听Socket
监听Socket通常使用listen()函数,该函数的原型为:
“`c
#include
// sockfd表示要监听的Socket,backlog表示等待连接队列的长度
int listen(int sockfd, int backlog);
“`
其中,sockfd表示要监听的Socket,backlog表示等待连接队列的长度。对于半连接状态的Socket,即已经接收到连接请求,但未完成连接的Socket,backlog无效。
4. 接收连接
接收连接通常使用accept()函数,该函数的原型为:
“`c
#include
// sockfd表示要监听的Socket,addr表示客户端的IP地址和端口号,addrlen表示地址长度
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
“`
其中,sockfd表示要监听的Socket,addr表示客户端的IP地址和端口号,addrlen表示地址长度。
accept()函数是一个阻塞函数,意味着程序会一直阻塞在这里,直到有客户端的连接请求到来。当有客户端的连接请求到来时,accept()函数返回一个新的Socket,用于和客户端进行通信。客户端的IP地址和端口号存储在addr所指向的地址中。
5. 发送和接收数据
发送和接收数据需要使用send()和recv()函数:
“`c
#include
#include
// sockfd表示Socket,buf表示发送或接收的数据,len表示发送或接收的字节数,flags表示数据的标志
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
“`
其中,sockfd表示Socket,buf表示发送或接收的数据,len表示发送或接收的字节数,flags表示数据的标志。
6. 关闭Socket
关闭Socket需要使用close()函数,该函数的原型为:
“`c
#include
// sockfd表示要关闭的Socket
int close(int sockfd);
“`
四、
相关问题拓展阅读:
#include
#include
#include
#include
#include
#include
#include
main()
{
int serverfd=socket(AF_INET,SOCK_STREAM,0);
if(serverfd==-1) printf(“服务器socket建立失败:%m\n”),exit(-1);
printf(“服务器socket建立成功!\n”);
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(11112);
inet_aton(“192.168.180.92”,&addr.sin_addr);
int r=bind(serverfd,(struct sockaddr*)&addr,sizeof(addr));
if(r==-1) printf(“绑定地址失败:%m\n”),exit(-1);
printf(“绑定地址成功!\悉哪n”);
r=listen(serverfd,10);
if(r==-1) printf(“监听服务socket变化失败:%m\n”),exit(-1);
printf(“监听服务器socket成功!\n”);
struct sockaddr_in caddr;
socklen_t len;
while(1)
{
len=sizeof caddr;
int fd=accept(serverfd,(struct sockaddr*)&caddr,&len);
printf(“有人连接:%s:%d\n”,
inet_ntoa(caddr.sin_addr),
ntohs(caddr.sin_port));
}
}
这是服务器端睁樱码的,客户端的只要去掉监听,连接,再把发送接收数据改一下,就能用了
server:
#include
#include
#include
#include
#include 链唯哗
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXDATASIZE
#define SERVPORT
#define BACKLOG 10
int SendFileToServ(const char *path, const char *FileName, const char *ip)
{
#define PORT 20232
int sockfd;
int recvbytes;
char buf;
char send_str;
char filepath = {0};
struct sockaddr_in serv_addr;
FILE *fp;
sprintf(filepath, “%s%s”, path, FileName);
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror(“socket”山纤);
return 1;
}
bzero(&serv_addr,sizeof(struct sockaddr_in));
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(PORT);
inet_aton(ip, &serv_addr.sin_addr);
int IErrCount = 0;
again:
if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr))==-1)
{
if (5 == IErrCount)
return 1;
IErrCount++;
perror(“connect”);
sleep(2);
goto again;
}
//if ((fp = fopen(FileName, “rb”)) == NULL)
if ((fp = fopen(filepath, “rb”)) == NULL)
{
perror(“fopen “);
return 1;
}
recvbytes = write(sockfd, FileName, strlen(FileName));
recvbytes = read(sockfd, buf, MAXDATASIZE);
if (!memcmp(buf, “sendmsg”, 7))
{
while(fgets(send_str, MAXDATASIZE, fp))
{
recvbytes = write(sockfd, send_str, strlen(send_str));
recvbytes = read(sockfd, buf, MAXDATASIZE);
if (recvbytes 0)
{
nret = SendFileToServ(path, FileName, str);
printf(“nret\n”, nret);
if (1 == nret)
write(client_fd, “send file error”, 15);
else if(2 == nret)
write(client_fd, “reload nginx error”, 18);
else
write(client_fd, “succ”, 4);
}
close(client_fd);
}
}
_________________________________________________
client:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXDATASIZE
#define SERVPORT 20232
#define BACKLOG 10
int mysyslog(const char * msg)
{
FILE *fp;
if ((fp = fopen(“/tmp/tmp.log”, “a+”)) == NULL)
{
return 0;
}
fprintf(fp, “\n”, msg);
fclose(fp);
return 0;
}
static void quit_handler(int signal)
{
kill(0, SIGUSR2);
syslog( LOG_NOTICE, “apuserv quit…”);
// do something exit thing ,such as close socket ,close mysql,free list
// …..
//i end
exit(0);
}
static int re_conf = 0;
static void reconf_handler(int signal)
{
re_conf=1;
syslog(LOG_NOTICE,”apuserv reload configure file .”);
// ????·???????1nf == 1£???′μ?????
static int isrunning(void)
{
int fd;
int ret;
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = 0;
lock.l_start = 0;
lock.l_len = 0;
const char *lckfile = “/tmp/dstserver.lock”;
fd = open(lckfile,O_WRON|O_CREAT);
if (fd < 0) {
syslog(LOG_ERR,”can not create lock file: %s\n”,lckfile);
return 1;
}
if ((ret = fcntl(fd,F_SETLK,&lock)) < 0) {
ret = fcntl(fd,F_GETLK,&lock);
if (lock.l_type != F_UNLCK) {
close(fd);
return lock.l_pid;
}
else {
fcntl(fd,F_SETLK,&lock);
}
}
return 0;
}
int main(int argc, char **argv)
{
int sockfd,client_fd;
socklen_t sin_size;
struct sockaddr_in my_addr,remote_addr;
char buff;
int recvbytes;
#if 1
int pid ;
char ch ;
int ret;
int debug = 0;
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGTERM, quit_handler);
syslog(LOG_NOTICE,”dstserver start….”);
while ((ch = getopt(argc, argv, “dhV”)) != -1) {
switch (ch) {
case ‘d’:
debug = 1;
break;
case ‘V’:
printf(“Version:%s\n”,”1.0.0″);
return 0;
case ‘h’:
printf(” -d use daemon mode\n”);
printf(” -V show version\n”);
return 0;
default:
printf(” -d use daemon mode\n”);
printf(” -V show version\n”);
}
}
if (debug && daemon(0,0 ) ) {
return -1;
}
if (isrunning()) {
fprintf(stderr, “dstserver is already running\n”);
syslog(LOG_INFO,”dstserver is already running\n”);
exit(0);
}
while (1) {
pid = fork();
if (pid < 0)
return -1;
if (pid == 0)
break;
while ((ret = waitpid(pid, NULL, 0)) != pid) {
syslog(LOG_NOTICE, “waitpid want %d, but got %d”, pid, ret);
if (ret < 0)
syslog(LOG_NOTICE, “waitpid errno:%d”, errno);
}
kill(0, SIGUSR2);
sleep(1);
syslog(LOG_NOTICE,”restart apuserver”);
}
signal(SIGHUP, reconf_handler);
signal(SIGPIPE, SIG_IGN);
signal(SIGUSR1,SIG_IGN);
signal(SIGUSR2, SIG_DFL);
signal(SIGTERM, SIG_DFL);
#endif
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror(“socket”);
exit(1);
}
bzero(&my_addr,sizeof(struct sockaddr_in));
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(SERVPORT);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1)
{
perror(“bind”);
exit(1);
}
if(listen(sockfd,BACKLOG)==-1)
{
perror(“listen”);
exit(1);
}
char filepath= {0};
FILE *fp;
while(1)
{
sin_size = sizeof(struct sockaddr_in);
if((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size))==-1)
{
perror(“falied accept”);
continue;
}
memset(buff, 0, MAXDATASIZE);
recvbytes = read(client_fd, buff, MAXDATASIZE);
sprintf(filepath, “/etc/nginx/url_rule/%s”, buff);
if ((fp = fopen(filepath, “wb”)) == NULL)
{
perror(“fopen”);
close(client_fd);
continue;
}
write(client_fd, “sendmsg”, 7);
while(read(client_fd, buff, MAXDATASIZE))
{
if (!memcmp(buff, “end”, 3))
{
fclose(fp);
break;
}
else
{
fprintf(fp, “%s”, buff);
write(client_fd, “goon”, 4);
}
}
//system(“nginx -s reload”);
char *Sptr = “nginx reload succ”;
char *Eptr = “nginx reload error”;
int ret;
ret = system(“nginx -s reload”);
printf(“ret\n”, ret);
if (ret != 0)
{
write(client_fd, Eptr, strlen(Eptr));
}
else
{
write(client_fd, Sptr, strlen(Sptr));
}
close(client_fd);
}
}
以前写的:内容忘记了。不是很复杂你可以自己看!
成都创新互联建站主营:成都网站建设、网站维护、网站改版的网站建设公司,提供成都网站制作、成都网站建设、成都网站推广、成都网站优化seo、响应式移动网站开发制作等网站服务。
网站标题:「图解」Linux上Socket通信的流程(linuxsocket通信流程图)
网页网址:http://www.csdahua.cn/qtweb/news28/277078.html
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网