
1 /* socket->bind->listen->accept->recv/recvfrom->send/sendto->close 2 3 客戶端:socket->connect->send/sendto->recv/recvfrom->close 4 5 其中服務器端首先建立起socket,然后調用本地端口的綁定,接著就開始與客服端建立聯系,并接收客戶端發送的消息。 6 客戶端則在建立socket之后調用connect函數來建立連接。 7 8 服務器端的源代碼如下所示: */ 9 10 /* "server.c" */ 11 12 #include<sys/types.h> 13 #include<sys/socket.h> 14 #include<stdio.h> 15 #include<stdlib.h> 16 #include<errno.h> 17 #include< string .h> 18 #include<unistd.h> 19 #include<netinet/ in .h> 20 21 #define PORT 3490 // 端口 22 23 #define BUFFER_SIZE 1024 // 緩沖區大小 24 25 #define MAX_QUE_CONN_NM 5 // 服務器等待連接隊列的最大長度。 26 27 int main(){ 28 29 struct sockaddr_in server_sockaddr,client_sockaddr; // 分別定義服務器和客戶端套接字 30 int sin_size,recvbytes; 31 int server_fd,client_fd; 32 char buf[BUFFER_SIZE]; // 緩沖區 33 34 /* 35 SOCKET PASCAL FAR socket( int af, int type, int protocol); 36 af:一個地址描述。目前僅支持AF_INET格式,也就是說ARPA Internet地址格式。 37 type:指定socket類型。新套接口的類型描述類型,如TCP(SOCK_STREAM)和UDP(SOCK_DGRAM)。 38 常用的socket類型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。 39 protocol:顧名思義,就是指定協議。套接口所用的協議。如調用者不想指定,可用0。 40 常用的協議有,IPPROTO_TCP、IPPROTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等, 41 它們分別對應TCP傳輸協議、UDP傳輸協議、STCP傳輸協議、TIPC傳輸協議。 42 */ 43 if ((server_fd = socket(AF_INET,SOCK_STREAM, 0 ))== - 1 ){ // 建立socket連接www.linuxidc.com 44 perror( " create socket fail " ); 45 exit( 1 ); 46 } 47 48 printf( " Socket id=%d\n " ,server_fd); 49 50 /* 設置sockaddr_in結構體中的相關參數 */ 51 52 server_sockaddr.sin_family = AF_INET; 53 server_sockaddr.sin_port = htons(PORT); // 由于在寫網絡程序時字節的網絡順序和主機順序會有問題 54 server_sockaddr.sin_addr.s_addr = INADDR_ANY; // 即0.0.0.0 任意地址 55 bzero(&(server_sockaddr.sin_zero), 8 ); 56 int i = 1 ; // 允許重復使用本地地址與套接字進行綁定 57 58 /* int PASCAL FAR setsockopt(SOCKET s,int level,int optname,const char FAR *optval,int optlen); 59 s:標識一個套接字的描述符。 60 level:選項定義的層次;目前僅支持SOL_SOCKET和IPPROTO_TCP層次。 61 optname:需設置的選項。 62 optval:指針,指向存放選項值的緩沖區。 63 optlen:optval緩沖區長度。 64 */ 65 setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR,&i, sizeof (i)); 66 67 /* 68 int bind(SOCKET socket, const struct sockaddr *address, 69 socklen_t address_len); 70 參數說明: 71 socket:是一個套接字。 72 address:是一個sockaddr結構指針,該結構中包含了要結合的地址和端口號。 73 address_len:確定address緩沖區的長度。 74 返回值:如果函數執行成功,返回值為0,否則為SOCKET_ERROR。 75 */ 76 if (bind(server_fd,( struct sockaddr *)&server_sockaddr, sizeof ( struct sockaddr)) == - 1 ){ // 綁定函數bind 77 perror( " bind fail " ); 78 exit( 1 ); 79 } 80 81 printf( " Bind success!\n " ); 82 83 /* 84 int PASCAL FAR listen( SOCKET s, int backlog); 85 S:用于標識一個已捆綁未連接套接口的描述字。 86 backlog:等待連接隊列的最大長度。 87 */ 88 if (listen(server_fd,MAX_QUE_CONN_NM)== - 1 ){ // 調用listen函數,創建為處理請求的隊列 89 perror( " listen fail " ); 90 exit( 1 ); 91 } 92 93 printf( " Listening......\n " ); 94 95 /* 96 SOCKET PASCAL FAR accept( SOCKET s, struct sockaddr FAR* addr,int FAR* addrlen); 97 s:套接口描述字,該套接口在listen()后監聽連接。 98 addr:(可選)指針,指向一緩沖區,其中接收為通訊層所知的連接實體的地址。Addr參數的實際格式由套接口創建時所產生的地址族確定。 99 addrlen:(可選)指針,輸入參數,配合addr一起使用,指向存有addr地址長度的整型數。 100 */ 101 if ((client_fd = accept(server_fd,( struct sockaddr *)&client_sockaddr,&sin_size))==- 1 ){ // 調用accept函數,等待客戶端的接 102 perror( " accept fail " ); 103 exit( 1 ); 104 } 105 106 printf( " server: got connection from %s \n " ,inet_ntoa(client_sockaddr.sin_addr)); 107 108 memset(buf, 0 , sizeof (buf)); 109 /* 110 int PASCAL FAR recv( SOCKET s, char FAR* buf, int len, int flags); 111 s:一個標識已連接套接口的描述字。 112 buf:用于接收數據的緩沖區。 113 len:緩沖區長度。 114 flags:指定調用方式。通常寫成0 115 */ 116 if ((recvbytes = recv(client_fd,buf,BUFFER_SIZE, 0 )) == - 1 ){ // 調用recv函數接收客戶端的請求 117 perror( " recv fail " ); 118 exit( 1 ); 119 } 120 121 printf( " Received a message: %s\n " ,buf); 122 123 124 /* 向客戶起寫數據 */ 125 if (write(client_fd, " 客戶端我收到你發來的數據了,你能收到這句應答嗎?\n " , 1024 )==- 1 ) 126 perror( " write error! " ); 127 128 close(client_fd); 129 130 close(server_fd); 131 exit( 0 ); 132 } 133 134 135 136 137 138 /* 客戶端 */ 139 /* client.c 運行方式:./client localhost */ 140 #include <stdio.h> 141 #include <stdlib.h> 142 #include <errno.h> 143 #include < string .h> 144 #include <netdb.h> 145 #include <sys/types.h> 146 #include <netinet/ in .h> 147 #include <sys/socket.h> 148 #define PORT 3490 149 #define MAXDATASIZE 5000 150 int main( int argc, char ** argv) 151 { 152 int sockfd,nbytes; 153 char buf[ 1024 ]; 154 struct hostent * he; 155 struct sockaddr_in srvaddr; 156 if (argc!= 2 ) 157 { 158 perror( " Usage:client hostname\n " ); 159 exit( 1 ); 160 } 161 /* 函數gethostbyname獲得指定域名地址所對應的ip地址 */ 162 if ((he=gethostbyname(argv[ 1 ]))== NULL) 163 { 164 perror( " gethostbyname " ); 165 exit( 1 ); 166 } 167 /* 創建套接字,返回套接字描述符 */ 168 if ((sockfd=socket(AF_INET,SOCK_STREAM, 0 ))==- 1 ) 169 { 170 perror( " create socket error " ); 171 exit( 1 ); 172 } 173 bzero(&srvaddr, sizeof (srvaddr)); 174 /* 用獲得的遠程服務器進程的ip地址和端口號來填充一個internet套接字地址結構 */ 175 srvaddr.sin_family= AF_INET; 176 srvaddr.sin_port= htons(PORT); 177 srvaddr.sin_addr=*(( struct in_addr *)he-> h_addr); 178 /* 用connect于這個遠程服務器建立一個internet連接 */ 179 if (connect(sockfd,( struct sockaddr *)&srvaddr, sizeof ( struct sockaddr))==- 1 ) 180 { 181 perror( " connect error " ); 182 exit( 1 ); 183 } 184 185 186 if ((send(sockfd, " 客戶端向服務端發送數據,服務端你收到了嗎? " , 1024 , 0 )) == - 1 ) 187 { 188 perror( " send error " ); 189 exit( 1 ); 190 } 191 192 193 194 /* 調用read函數讀取服務器write過來的信息 */ 195 if ((nbytes=read(sockfd,buf,MAXDATASIZE))==- 1 ) 196 { 197 perror( " read error " ); 198 exit( 1 ); 199 } 200 buf[nbytes]= ' \0 ' ; 201 printf( " read: %s " ,buf); 202 close(sockfd); 203 }
?
運行方式: gcc -o service service.c
gcc -o client client.c
chmod +x service
chmod +x client
在一個終端運行:./service
在另一個終端運行:./client localhost
服務端輸出:
Socket id=3 Bind success! Listening...... server: got connection from 127.0.0.1 Received a message: 客戶端向服務端發送數據,服務端你收到了嗎?
?
客戶端輸出:
read: 客戶端我收到你發來的數據了,你能收到這句應答嗎?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
