套接字是網絡通信的基礎,特別是C/C++編程中隨處可見,所以不得不知,不得不學。
那麼什麼是套接字?請參考另一篇文章:
https://blog.csdn.net/fengxianghui01/article/details/104398214
在這一篇文章中就只討論怎樣創建套接字並實現通信。既然是通信,那肯定是雙方的,所以一般稱通信的雙方爲“服務端”和“客戶端”。顧名思義,“服務端”是提供服務的一段,“客戶端”是訪問的一段。其實就是通信的兩端,不要去糾結兩端誰是誰。兩者不只是名字上的區別,在創建套接字的時候也區別。創建流程爲:
服務端:創建套接字的流程(創建->綁定->監聽->連接)
客戶端:創建套接字的流程(創建->連接)
點對點的單一通信方式。下面貼代碼,直接點:
// 服務端
// server.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <pthread.h>
#include <fcntl.h>
#define PORT 5000
int sockfd;
void init_sock_communication()
{
int nbytes = 0;
int flags;
char buffer[1024];
struct sockaddr_in server_addr;
/* 服務器端開始建立 socket 描述符 */
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
fprintf(stderr, "Socketerror:%s\n\a", strerror(errno));
exit(1);
}
/* 服務器端填充 sockaddr 結構 */
bzero(&server_addr, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORT);
/* 捆綁 sockfd 描述符 */
if (bind(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1)
{
fprintf(stderr, "Binderror:%s\n\a", strerror(errno));
exit(1);
}
printf("Server Port : %d ... ...\n", PORT);
/* 監聽 sockfd 描述符 */
if (listen(sockfd, 2) == -1)
{
fprintf(stderr, "Listenerror:%s\n\a", strerror(errno));
exit(1);
}
printf("create sock succeed!\n");
}
int main()
{
int sin_size, new_fd;
struct sockaddr_in client_addr;
init_sock_communication();
// 服務器阻塞,直到客戶程序建立連接
sin_size = sizeof(struct sockaddr_in);
while(1)
{
new_fd = accept(sockfd, (struct sockaddr *)(&client_addr), &sin_size);
printf("receive new client connect!");
}
}
// client.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <pthread.h>
#include <fcntl.h>
static char serverIP[32] = "192.168.216.130";
int sockfd;
#define TRUE 1
#define SUCCEED 1
#define FAILED 0
#define PORT 5000
int connect_server()
{
struct hostent *host;
struct sockaddr_in server_addr;
uint8_t strhost[32];
int iLoop = 5;
snprintf(strhost, 32, "%s", serverIP);
if((host = gethostbyname(strhost)) == NULL)
{
fprintf(stderr, "Get host name error\n");
exit(1);
}
printf("Ready to connect server ... ...\n");
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
while(iLoop--)
{
if(connect(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == 0)
{
iLoop = 5;
printf("connect server succeed! ... ...\n");
return SUCCEED;
}
printf("reconnect the server , %d ... ...\n", iLoop);
sleep(1);
}
printf("connect the server failed, Error Message : [%s]\n", strerror(errno));
return FAILED;
}
int main(int argc, char *argv[])
{
int running = 1;
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
fprintf(stderr, "create socket error : %s\n!", strerror(errno));
exit(1);
}
//連接服務器/初始化接收消息線程/客戶端工作線程初始化
if(connect_server())
{
close(sockfd);
exit(1);
}
}
編譯執行後:
cient:
Ready to connect server ... ...
connect server succeed! ... ...
就這麼簡單,創建了一個TCP套接字。當然UDP套接字更簡單。