2023年7月15日发(作者:)
socket通信详解(附代码)socket通信详解(附代码)socket简介 在计算机领域,socket是计算机之间进⾏通信的⼀种约定或者⽅式,通过socket这种约定,⼀台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。1. IP地址本机IP地址是127.0.0.1,当需要通信时,需要将IP地址封装到要发送的数据包中,路由器可以找到⽬标计算机,并将数据包传递给它,完成⼀次单向通信。2. 端⼝(Port) ⼀台计算机可以同时提供多种⽹络服务,Web服务,FTP服务,SMTP服务(邮箱),仅有IP地址,计算机可以正常接收到数据包,但是不知道选取那个⽹络程序来处理。为了区分不同的⽹络程序,计算机会为每个⽹络程序分配⼀个独⼀⽆⼆的端⼝号。 端⼝(Port)是⼀个虚拟的、逻辑上的概念。可以将端⼝理解为⼀道门,数据通过这道门流⼊流出,每道门有不同的编号,就是端⼝号。3. 协议协议是⽹络通信的约定,通信双⽅必须都遵守才能正常收发数据。协议有很多种,例如TCP、UDP、IP等。协议族是⼀组协议的统称。最常⽤的是TCP/IP协议族,它包含了TCP、IP、UDP、Telnet、FTP、SMTP等。由于TCP、IP是常⽤的底层协议,所以把他们统称TCP/IP协议族。4. 数据传输⽅式计算机之间有很多数据传输⽅式,常⽤的有SOCK_STREAM和SOCK_DGRAM.(1) SOCK_STREAM表⽰⾯向连接的数据⽅式。数据可以准确⽆误的到达另⼀台计算机。如果出现损坏或者丢失,将会重新发送,因此效率较低。常见的HTTP协议就是使⽤SOCK_STREAM传输数据。(2)SOCK_DGRAM表⽰⽆连接的数据传输⽅式。计算机只管传输数据,不做数据校验。如果传输中损坏或者丢失,⽆法找回,SOCK_STREAM不会频繁的丢失数据。因此效率较⾼。有可能多种协议使⽤同⼀种数据传输⽅式,所以在socket编程中需要同时指明数据传输⽅式和协议。Linux socket编程演⽰需要实现的功能:客户端从服务器端读取⼀个字符串并打印出来。:#include
//将套接字serv_sock与特定的IP地址和端⼝绑定,IP地址和端⼝都保存在sockaddr_in结构体中 bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
/*进⼊被动监听状态,等待⽤户发起请求。所谓被动监听, 是指套接字⼀直处于“睡眠”中,直到客户端发起请求才会被“唤醒”*/ listen(serv_sock, 20);
//接收客户端请求 struct sockaddr_in clnt_addr; socklen_t clnt_addr_size = sizeof(clnt_addr); //程序⼀旦执⾏到accept就会被堵塞(暂停运⾏),直到客户端发起请求 int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, $clnt_addr_size);
//向客户端发送数据 char str[] = "Hello World"; //向套接字写⼊数据 write(clnt_sock, str, sizeof(str));
//关闭套接字 close(clnt_sock); close(serv_sock);
return 0;
}:#include
//向服务器发起请求(特定的IP和端⼝) struct sockaddr_in serv_addr; memset($serv_addr, 0, sizeof(serv_addr));//⽤0填充每个字节 serv__family = AF_INET;//使⽤IPv4地址 serv__addr.s_addr = inet_addr("127.0.0.1"); serv__port = htons(1234); connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
//读取服务器传回的数据 char buffer[40]; read(sock, buffer, sizeof(buffer)-1);
printf("Message from server: %sn", buffer);
//关闭套接字 close(sock);
return 0;
}先编译运⾏,正常情况下,程序运⾏到accept()处就会堵塞,处于监听状态,等待客户端发送请求。接下来运⾏, 通过connect()函数向server发送请求,处于监听状态的server被激活,执⾏accept()函数,接收客户端发送的请求,然后执⾏write()函数向client传回数据。client接收到传回的数据后,connect就结束了,然后在利⽤read()将数据读出来。需要注意的是:(1)本程序server只接收⼀次client请求,当server向client传回数据后,程序就停⽌了。如果想再次收到服务器的数据,必须再次运⾏server.(2)server通过connect向服务器发送请求,服务器的IP地址和端⼝号保存在sockaddr_in结构体中。直到服务器传回数据后,connect()才结束运⾏。windows socket程序演⽰windows下socket程序和Linux思路相同,但细节有所差别:(1) Windows 下的 socket 程序依赖 或 ws2_,必须提前加载。DLL 有两种加载⽅式,将在下篇⽂章中讲解。(2) Linux使⽤“⽂件描述符”概念,⽽Windows使⽤”⽂件句柄“的概念;Linux不区分socket⽂件和普通⽂件,⽽Windows区分;Linux下socket()函数的返回为int类型,⽽Windows下为SOCKET类型,也就是句柄。(3) Linux下使⽤read()/write()函数读写,⽽Windows下使⽤recv()/send()函数进⾏发送和接收。(4)关闭socket时,Linux使⽤close()函数,⽽Windows使⽤closesocket()函数。:#include
//创建套接字 SOCKET servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //绑定套接字 sockaddr_in sockAddr; memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都⽤0填充 _family = PF_INET; //使⽤IPv4地址 _addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址 _port = htons(1234); //端⼝ bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
//进⼊监听状态 listen(servSock, 20);
//接收客户端请求 SOCKADDR clntAddr; int nSize = sizeof(SOCKADDR); SOCKET clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &nSize); //向客户端发送数据 char *str = "Hello World!"; send(clntSock, str, strlen(str)+sizeof(char), NULL); //关闭套接字 closesocket(clntSock); closesocket(servSock); //终⽌ DLL 的使⽤ WSACleanup(); return 0;
}:#include
//向服务器发起请求 sockaddr_in sockAddr; memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都⽤0填充 _family = PF_INET; _addr.s_addr = inet_addr("127.0.0.1"); _port = htons(1234); connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
//接收服务器传回的数据 char szBuffer[MAXBYTE] = {0}; recv(sock, szBuffer, MAXBYTE, NULL); //输出接收到的数据 printf("Message form server: %sn", szBuffer); //关闭套接字 closesocket(sock); //终⽌使⽤ DLL WSACleanup(); system("pause"); return 0;}
发布者:admin,转转请注明出处:http://www.yc00.com/news/1689410765a243614.html
评论列表(0条)