什么是socket?
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。其实socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)
socket的作用是用于网络通讯,网络通讯一般指的是不同主机之间的进程通讯,比如我电脑上的qq和你电脑上的qq实现通讯,都是进程之间发送数据.
在本地用pid标识一个进程,在网络中,tcp/ip协议的网络层“ip地址”可以唯一标识网络中的主机,传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互
socket服务端编程基本步骤:
1,创建套接字, 利用socket函数
2,绑定套接字: bind
3,监听套件字: listen
4,accept,接收客户端的连接,3次握手就发生在这个阶段, 这个函数返回一个新的套接字
5,处理业务
socket客户端:
1,创建套接字: socket
2,连接服务端: connect
3,处理业务
----------------------------------------------------------------------------------------------------------------------------------
服务端源码:
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/socket.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <arpa/inet.h> 7 #include <unistd.h> 8 9 int main(int argc, char *argv[]) 10 { 11 int sockfd = -1; 12 int bindres = -1; 13 int listenres = -1; 14 15 sockfd = socket( AF_INET, SOCK_STREAM, 0 ); 16 if ( -1 == sockfd ) { 17 perror( "sock created" ); 18 exit( -1 ); 19 } 20 21 struct sockaddr_in server; 22 memset( &server, 0, sizeof( struct sockaddr_in ) ); 23 server.sin_family = AF_INET; 24 server.sin_port = 6666; 25 server.sin_addr.s_addr = htonl( INADDR_ANY ); 26 27 bindres = bind( sockfd, (struct sockaddr*)&server, sizeof( server ) ); 28 if( -1 == bindres ) { 29 perror( "sock bind" ); 30 exit( -1 ); 31 } 32 33 listenres = listen( sockfd, SOMAXCONN ); 34 if( -1 == listenres ) { 35 perror( "sock listen" ); 36 exit( -1 ); 37 } 38 39 struct sockaddr_in peerServer; 40 int acceptfd = -1; 41 socklen_t len = sizeof( peerServer ); 42 acceptfd = accept( sockfd, (struct sockaddr*)&peerServer, &len ); 43 if ( -1 == acceptfd ) { 44 perror( "sock accept" ); 45 exit( -1 ); 46 } 47 48 char recvBuf[1024]; 49 while( 1 ) { 50 memset( recvBuf, 0, sizeof( recvBuf ) ); 51 int recvBytes = read( acceptfd, recvBuf, sizeof( recvBuf ) ); 52 fputs( recvBuf, stdout ); 53 write( acceptfd,recvBuf, recvBytes ); 54 } 55 56 close( sockfd ); 57 close( acceptfd ); 58 59 return 0; 60 }
客户端源码:
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/socket.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <arpa/inet.h> 7 #include <unistd.h> 8 9 int main(int argc, char *argv[]) 10 { 11 int sockfd = -1; 12 13 sockfd = socket( AF_INET, SOCK_STREAM, 0 ); 14 if ( -1 == sockfd ) { 15 perror( "sock created" ); 16 exit( -1 ); 17 } 18 19 struct sockaddr_in server; 20 memset( &server, 0, sizeof( struct sockaddr_in ) ); 21 server.sin_family = AF_INET; 22 server.sin_port = 6666; 23 server.sin_addr.s_addr = inet_addr( "127.0.0.1" ); 24 25 int res = -1; 26 res = connect( sockfd, (struct sockaddr*)&server, sizeof( server ) ); 27 if( -1 == res ){ 28 perror( "sock connect" ); 29 exit( -1 ); 30 } 31 32 char sendBuf[1024] = { 0 }; 33 char recvBuf[1024] = { 0 }; 34 while( fgets( sendBuf, sizeof( sendBuf ), stdin ) != NULL ) { 35 write( sockfd, sendBuf, sizeof( sendBuf ) ); 36 read( sockfd, recvBuf, sizeof( recvBuf ) ); 37 fputs( recvBuf, stdout ); 38 memset( sendBuf, 0, sizeof( sendBuf ) ); 39 memset( recvBuf, 0, sizeof( recvBuf ) ); 40 } 41 42 close( sockfd ); 43 44 return 0; 45 }
备注:
1、socket函数的参数:当protocol为0时,会自动选择type类型对应的默认协议
2、将sin_addr设置为INADDR_ANY"的含义是什么?
转换过来就是0.0.0.0,泛指本机的意思,也就是表示本机的所有IP,因为有些机子不止一块网卡,多网卡的情况下,这个就表示所有网卡ip地址的意思。 比如一台电脑有3块网卡,分别连接三个网络,那么这台电脑就有3个ip地址了,如果某个应用程序需要监听某个端口,那他要监听哪个网卡地址的端口呢? 如果绑定某个具体的ip地址,你只能监听你所设置的ip地址所在的网卡的端口,其它两块网卡无法监听端口,如果我需要三个网卡都监听,那就需要绑定3个ip,也就等于需要管理3个套接字进行数据交换,这样岂不是很繁琐? 所以出现INADDR_ANY,你只需绑定INADDR_ANY,管理一个套接字就行,不管数据是从哪个网卡过来的,只要是绑定的端口号过来的数据,都可以接收到