[linux][c语言]用socket实现简单的服务器客户端交互
Socket解釋:
網絡上的兩個程序通過一個雙向的通信連接實現數據的交換,這個連接的一端稱為一個socket。
Socket的英文原義是“孔”或“插座”。作為BSD UNIX的進程通信機制,取后一種意思。通常也稱作"套接字",用于描述IP地址和端口,是一個通信鏈的句柄,可以用來實現不同虛擬機或不同計算機之間的通信。在Internet上的主機一般運行了多個服務軟件,同時提供幾種服務。每種服務都打開一個Socket,并綁定到一個端口上,不同的端口對應于不同的服務。Socket正如其英文原意那樣,像一個多孔插座。一臺主機猶如布滿各種插座的房間,每個插座有一個編號,有的插座提供220伏交流電, 有的提供110伏交流電,有的則提供有線電視節目。 客戶軟件將插頭插到不同編號的插座,就可以得到不同的服務。
連接過程:
根據連接啟動的方式以及本地套接字要連接的目標,套接字之間的連接過程可以分為三個步驟:服務器監聽,客戶端請求,連接確認。
(1)服務器監聽:是服務器端套接字并不定位具體的客戶端套接字,而是處于等待連接的狀態,實時監控網絡狀態。
(2)客戶端請求:是指由客戶端的套接字提出連接請求,要連接的目標是服務器端的套接字。為此,客戶端的套接字必須首先描述它要連接的服務器的套接字,指出服務器端套接字的地址和端口號,然后就向服務器端套接字提出連接請求。
(3)連接確認:是指當服務器端套接字監聽到或者說接收到客戶端套接字的連接請求,它就響應客戶端套接字的請求,建立一個新的線程,把服務器端套接字的描述發給客戶端,一旦客戶端確認了此描述,連接就建立好了。而服務器端套接字繼續處于監聽狀態,繼續接收其他客戶端套接字的連接請求。
mac環境編譯
client.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> /* netdb is necessary for struct hostent */#define PORT 4321 /* server port */#define MAXDATASIZE 100int main(int argc, char *argv[])
{int sockfd, num; /* files descriptors */char buf[MAXDATASIZE]; /* buf will store received text */struct hostent *he; /* structure that will get information about remote host */struct sockaddr_in server;if (argc != 2){printf("Usage: %s <IP Address>\n",argv[0]);exit(1);}if((he=gethostbyname(argv[1]))==NULL){printf("gethostbyname() error\n");exit(1);}if((sockfd=socket(AF_INET,SOCK_STREAM, 0))==-1){printf("socket() error\n");exit(1);}bzero(&server,sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(PORT);server.sin_addr = *((struct in_addr *)he->h_addr);if(connect(sockfd, (struct sockaddr *)&server, sizeof(server))==-1){printf("connect() error\n");exit(1);}char str[] = "你好啊服務器!\n";if((num=send(sockfd,str,sizeof(str),0))==-1){printf("send() error\n");exit(1);}if((num=recv(sockfd,buf,MAXDATASIZE,0))==-1){printf("recv() error\n");exit(1);}buf[num-1]='\0';printf("server message: %s\n",buf);close(sockfd);return 0;
}
server.c
#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>#define PORT 4321#define BACKLOG 1
#define MAXRECVLEN 1024int main(int argc, char *argv[])
{char buf[MAXRECVLEN];int listenfd, connectfd; /* socket descriptors */struct sockaddr_in server; /* server's address information */struct sockaddr_in client; /* client's address information */socklen_t addrlen;/* Create TCP socket */if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){/* handle exception */perror("socket() error. Failed to initiate a socket");exit(1);}/* set socket option */int opt = SO_REUSEADDR;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));bzero(&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(PORT);server.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(listenfd, (struct sockaddr *)&server, sizeof(server)) == -1){/* handle exception */perror("Bind() error.");exit(1);}if(listen(listenfd, BACKLOG) == -1){perror("listen() error. \n");exit(1);}addrlen = sizeof(client);while(1){if((connectfd=accept(listenfd,(struct sockaddr *)&client, &addrlen))==-1){perror("accept() error. \n");exit(1);}struct timeval tv;gettimeofday(&tv, NULL);printf("You got a connection from client's ip %s, port %d at time %ld.%ld\n",inet_ntoa(client.sin_addr),htons(client.sin_port), tv.tv_sec,tv.tv_usec);int iret=-1;while(1){iret = recv(connectfd, buf, MAXRECVLEN, 0);if(iret>0){printf("%s\n", buf);}else{close(connectfd);break;}/* print client's ip and port */send(connectfd, buf, iret, 0); /* send to the client welcome message */}}close(listenfd); /* close listenfd */return 0;
}
命令行執行
$ gcc client.c -o client,可以編譯出客戶端程序。
命令行執行$ gcc server.c -o server,可以編譯出服務端程序。
命令行執行
$ ./server,啟動server程序。重新打開一個命令行窗口
執行$ ./client 127.0.0.1,啟動客戶端程序
本程序客戶端會自動退出,服務器不會,因此如果想停掉服務器程序,直接在命令行界面按鍵盤Ctrl+C停止。
程序實現的功能很簡單,就是服務器監聽4321端口,客戶端與之建立TCP連接后,再發送字符串
“你好啊服務器!\n”到服務端,服務端打印出來,然后再把字符串傳回給客戶端,客戶端再打印出來。然后客戶端關閉連接退出,而服務端繼續監聽4321端口等待下一次連接。
轉載于:https://www.cnblogs.com/-oreo/p/10013216.html
總結
以上是生活随笔為你收集整理的[linux][c语言]用socket实现简单的服务器客户端交互的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三星堆博物馆学生票包括哪些
- 下一篇: 金铲铲之战对战记录怎么隐藏?