初學socket編程

做項目經查遇到socket(套接字)的地方,業務的地方大部分直接調用接口,讀取到內容後再返回給接口就ok了,但學習要深究其原理,因此決定學習下socket相關的內容,該文章參考了下面這位大佬的文章,不做搬運工,寫下自己的理解;

https://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html#!comments

linux上通信和通信協議TCP中的三次握手沒有直接聯繫,學習學的三次握手和四次握手釋放都是很底層的東西,linux編程提供了socket.h 的頭文件,裏面有封裝好的服務端和客戶端的接口,接口類似於下的

extern int socket (int __domain, int __type, int __protocol) __THROW; 創建
extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) __THROW; 綁定ip 端口
extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len); 連接 
extern ssize_t send (int __fd, const void *__buf, size_t __n, int __flags); 發送 
extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags);        接收
extern int listen (int __fd, int __n) __THROW;                                 監聽
extern int accept (int __fd, __SOCKADDR_ARG __addr,socklen_t *__restrict __addr_len); 接收
extern int shutdown (int __fd, int __how) __THROW;                               關閉連接

socket.h頭文件在linux系統下都有 很多種

root[/usr]%find . | grep socket.h
./include/asm/socket.h
./include/asm-generic/socket.h
./include/linux/caif/caif_socket.h
./include/linux/netfilter/xt_socket.h
./include/linux/socket.h
./include/bits/socket.h
./include/sys/socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/arch/x86/include/uapi/asm/socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/include/config/ieee802154/socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/include/config/netfilter/xt/match/socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/include/linux/socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/include/uapi/asm-generic/socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/include/uapi/linux/caif/caif_socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/include/uapi/linux/netfilter/xt_socket.h
./src/kernels/3.10.0-957.21.3.el7.x86_64.debug/include/uapi/linux/socket.h

在服務端要用先調用socket、bind、listen後,循環中等待 accpt recv 等

在客戶端 依次是socket 、 connect、send 等 

下面是我測試的代碼

服務端:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>

#define MAXLINE 4096
int main(int argc, char** argv){    
	int    listenfd, connfd;    
	struct sockaddr_in     servaddr;    
	char    buff[4096],sendbuff[4096];    
	int     n;    
	//創建socket服務端 調用socket() 函數
	if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
		printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);    
		exit(0);    
		}    
	memset(&servaddr, 0, sizeof(servaddr));    
	servaddr.sin_family = AF_INET;    
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);    
	servaddr.sin_port = htons(6666);  
	//調用函數bind() 綁定ip 端口
	if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){    
		printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);    
		exit(0);    }  
		// 調用listen()函數  準備接受客戶端
	if( listen(listenfd, 10) == -1){   
		printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno); 
		exit(0);    
	}    
	printf("======waiting for client's request======\n");    
	while(1){
		//調用函數accept() 獲取得到的socket包
		struct sockaddr* client_addr = NULL;
		
		if( (connfd = accept(listenfd, client_addr, NULL)) == -1){    
		printf("accept socket error: %s(errno: %d)",strerror(errno),errno);        
		continue;    
		}
		// 調用recv 函數獲取內容
		n = recv(connfd, buff, MAXLINE, 0);    
		buff[n] = '\0';   
		printf("recv msg from client: %s\n", buff); 
		for (int i = 0; i <n;i++)
		{
			sendbuff[i] = buff[n-1-i];
		}
		sendbuff[n] = '\0';
		n = send(connfd,sendbuff,MAXLINE,0);
		printf("此次連接:%d 即將關閉",connfd);
		// 關閉連接
		//shutdown(connfd,SHUT_RDWR);   
		close(connfd);
		}   
		shutdown(listenfd,SHUT_RDWR);
	}

客戶端:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>

#define MAXLINE 4096

int main(int argc, char** argv)
{
    int    sockfd, n;
    char    recvline[4096], sendline[4096];
    struct sockaddr_in    servaddr;

    if( argc != 2){
    printf("usage: ./client <ipaddress>\n");
    exit(0);
    }

    if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
    printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
    exit(0);
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(6666);
    if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){
    printf("inet_pton error for %s\n",argv[1]);
    exit(0);
    }

    if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){
    printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }

    printf("send msg to server: \n");
    fgets(sendline, 4096, stdin);
    if( send(sockfd, sendline, strlen(sendline), 0) < 0)
    {
    printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
    exit(0);
    }
	if (recv(sockfd, recvline, strlen(sendline), 0) < 0)
	{
		printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
		exit(0);
	}
	printf("recv msg from server: %s\n",recvline);

    close(sockfd);
    exit(0);
}

至於將的協議 其他之類 暫時不熟悉 不表。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章