要實現一個服務器,其實主要是對socket編程的理解。這裏運用到了Socket編程的面向鏈接的編程,其流程以下:
編程
下面直接貼代碼了。
服務器
一、服務器端程序socket
(1)代碼tcp
/** * @file : tcpserver.c * @brief: A simple Tcp server * @author: ToakMa <mchgloak1120@163.com> * @date: 2014/10/09 */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> #include <strings.h> #include <arpa/inet.h> #define PORT 9000 #define WAIT_QUEUE_LEN 5 #define BUFF_SIZE 1024 #define WELCOME "### Welcome to my server ^_^! ###\n" int main(int argc, char *argv[]) { int serverfd, clientfd; struct sockaddr_in saddr; struct sockaddr_in caddr; socklen_t c_addrlen; int res; int len; char buff[BUFF_SIZE]; //1. create socket serverfd = socket(AF_INET, SOCK_STREAM, 0); if (-1 == serverfd) { perror("server socket : "); return -1; } printf("server socket create succ!\n"); //2. prepare IP and port //memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = htons(PORT); saddr.sin_addr.s_addr = INADDR_ANY; //inet_aton("192.168.0.100", &(saddr.sin_addr)); bzero(&(saddr.sin_zero), 8); //3. bind res = bind(serverfd, (struct sockaddr *)&saddr, sizeof(struct sockaddr)); if (-1 == res) { perror("server bind: "); return -1; } printf("bind succ!\n"); //4. listen res = listen(serverfd, WAIT_QUEUE_LEN); if (-1 == res) { perror("server listen : "); return -1; } printf("server listen...\n"); //5. accept c_addrlen = sizeof(struct sockaddr_in); clientfd = accept(serverfd, (struct sockaddr *)&caddr, &c_addrlen); if (-1 == clientfd) { perror("server accept: "); return -1; } printf("server have a client, IP: %s \n", inet_ntoa(caddr.sin_addr)); //6.send a welcome send(clientfd, WELCOME, strlen(WELCOME), 0); //7. interactive while ((len = recv(clientfd, buff, BUFF_SIZE, 0)) > 0) { buff[len] = '\0'; printf("recv msg is : %s \n", buff); if (send(clientfd, buff, len, 0) < 0) { perror("server send: "); return -1; } } //8. close close(clientfd); close(serverfd); return 0; }
(2)程序理解:函數
經過socket()函數建立了一個套接字,而後將套接字綁定到主機全部本地地址的TCP端口9000上。接着listen()系統調用建立5個等待隊列,等待客戶端鏈接請求的到達。當一個鏈接請求到達時,accept系統調用會返回一個新的套接字描述符,用來描述遠程的客戶端鏈接。原來的套接字仍然用來接收其餘客戶端的請求。 而後即是一些交互:發送和接受數據的處理。最後,關閉套接字。測試
(3)telnet測試效果:ui
爲了更好地理解面向鏈接的Socket編程模型,下面寫一個客戶端程序來測試。spa
二、客戶端程序.net
(1)代碼:
code
/** * @file: tcpclient.c * @brief: A simple Tcp client * @author: ToakMa <mchgloak1120@163.com> * @date: 2014/10/09 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 9000 #define BUFF_SIZE 1024 int main(int argc, char *argv[]) { int sockfd; int recv_len, send_len; struct sockaddr_in remote_addr; char buff[BUFF_SIZE]; int res; //1. create socket sockfd = socket(AF_INET, SOCK_STREAM, 0); if (-1 == sockfd) { perror("client socket :"); return -1; } //2. prepare ip and port memset(&remote_addr, 0, sizeof(remote_addr)); remote_addr.sin_family = AF_INET; remote_addr.sin_port = htons(PORT); remote_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); bzero(&(remote_addr.sin_zero), 8); //3. connect to server res = connect(sockfd, (struct sockaddr *)&remote_addr, sizeof(remote_addr)); if (-1 == res) { perror("client connect: "); return -1; } printf("client connect server succ!\n"); //4. recv sth recv_len = recv(sockfd, (struct sockaddr *)&remote_addr, sizeof(remote_addr), 0); buff[recv_len] = '\0'; printf(" %s ", buff); //5. interactive while (1) { printf("Enter string to send: "); scanf("%s", buff); if (!strcmp(buff, "quit")) break; send_len = send(sockfd, buff, strlen(buff), 0); recv_len = recv(sockfd, buff, BUFF_SIZE, 0); buff[recv_len] = '\0'; printf(" received: %s \n", buff); } //6. close close(sockfd); return 0; }
(2)程序理解:
首先建立了套接字,並和本機的TCP端口9000創建鏈接。若是鏈接成功,將會受到server發來的一個welcome,而後就能夠進行通訊了。
(3)測試:
首先運行服務器,而後運行客戶端,其運行效果以下:
代碼源碼地址:http://www.oschina.net/code/snippet_1241861_39180