socket网络编程(TCP UDP)demo

一、socket

在Linux中的网络编程是通过socket接口来进行的。人们常说的socket接口是一种特殊的I/O,它也是一种文件描述符。每一个socket都用一个半相关描述{协议,本地地址、本地端口}来表示;一个完整的套接字则用一个相关描述{协议,本地地址、本地端口、远程地址、远程端口}。socket也有一个类似于打开文件的函数调用,该函数返回一个整型的socket描述符,随后的连接建立、数据传输等操作都是通过socket来实现的。

二、socket常用API

1.创建套接字

int socket(int domain, int type, int protocol);

domain:域。
AF_INET/PF_INET:网际协议
AF_UNIX/PF_UNIX:本地协议,可写成AF_LOCAL/PF_LOCAL
type:类型。
SOCK_STREAM:流式套接字
SOCK_DGRAM:数据报套接字
protocol:协议。
一般为0

返回值:
成功:待连接套接字
失败:-1

备注:在网际协议中,选择流式套接字就代表TCP协议,选择数据报套接字就代表UDP协议,第三个参数protocol一般都不用。

2、绑定套接字与网络地址

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

sockfd:待连接套接字
addr:包含本地地址(IP+PORT)的通用地址结构体的指针
addrlen:地址结构体大小

通用地址结构体的定义:

struct sockaddr
{
sa_family_t  sa_family;
char        sa_data[14];
};

特殊地址结构体 —— IPv4地址结构体:

struct sockaddr_in
{           
       u_short sin_family;	// 地址族
       u_short sin_port;	// 端口
       struct in_addr sin_addr;	// IPV4地址
       char sin_zero[8];
};

struct in_addr
{
in_addr_t s_addr;	// 无符号32位网络地址
};

3.将待连接套接字设置为监听套接字,并设置最大同时接收连接请求个数

int listen(int sockfd, int backlog);

sockfd:待连接套接字
backlog:最大同时接收连接请求个数

返回值:
成功:0,并将sockfd设置为监听套接字
失败:-1

4、等待对端连接请求

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

sockfd:监听套接字
addr:通用地址结构体,用以存储对端地址(IP+PORT)
addrlen:参数addr的存储区域大小

返回值:
成功:已连接套接字(非负整数)
失败:-1

5、连接对端监听套接字

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

sockfd:待连接套接字
addr:包含对端地址(IP+PORT)的通用地址结构体的指针
addrlen:地址结构体大小

返回值:
成功:0
失败:-1

6.断开本端连接套接字

int close(int fd);

fd:已连接套接字

返回值:
成功:0
失败:-1

7.字节序转换

uint32_t htonl(uint32_t hostlong);   //h -> host 主机   n ->net 网络 
uint16_t htons(uint16_t hostshort);  //l -> long 长4    s -> short 短2
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

hostlong: 主机字节序的长整型数据
hostshort: 主机字节序的短整型数据
netlong: 网络字节序的长整型数据
netshort: 网络字节序的短整型数据

返回值:
对应的字节序数据

三、TCP demo

服务端

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

int main(int argc, char **argv)
{
	int s_fd;
	int c_fd;
	int pid;
	char sendbuf[128];
	char recvbuf[128];
	
	struct sockaddr_in s_addr;
	struct sockaddr_in c_addr;
	
	memset(&s_addr,0,sizeof(struct sockaddr_in));
	memset(&c_addr,0,sizeof(struct sockaddr_in));
	
	//1.socket
	s_fd = socket(AF_INET, SOCK_STREAM, 0);	
	if(s_fd == -1){
		perror("socket");
		exit(-1);
	}
	
	//2.bind
	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(atoi(argv[2]));
	inet_aton(argv[1],&s_addr.sin_addr);
	bind(s_fd,(struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));
	
	//3.listen
	listen(s_fd, 10);
	
	//4.accept
	int c_len = sizeof(struct sockaddr_in);
	while(1){
	
		c_fd = accept(s_fd,(struct sockaddr *)&c_addr, &c_len);
		if(c_fd == -1){
			perror("accept");
			exit(-1);
		}
		printf("========客户端已连接========\n");
		pid = fork();
		if(pid == 0){
			while(1){
				memset(recvbuf,0,sizeof(recvbuf));
				read(c_fd,recvbuf, 128);
				if(strstr(recvbuf,"quit") != NULL){
					write(c_fd,"client quit",20);
					printf("========客户端已退出========\n");
					break;
				}else{
					printf("客户端: %s",recvbuf);
				}
			}
		}
		else if(pid > 0){
			while(1){
				memset(sendbuf,0,sizeof(sendbuf));
				fgets(sendbuf,128,stdin);
				write(c_fd,sendbuf, strlen(sendbuf));			
			}
		}	
	}
	close(s_fd);		
	close(c_fd);		
	return 0;
}

客户端

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

int main(int argc, char **argv)
{
	int c_fd;
	int pid;
	char sendbuf[128];
	char recvbuf[128];
	struct sockaddr_in c_addr;
	
	memset(&c_addr,0,sizeof(struct sockaddr_in));
	
	//1.socket
	c_fd = socket(AF_INET, SOCK_STREAM, 0);	
	if(c_fd == -1){
		perror("socket");
		exit(-1);
	}
	
	//2.connect	
 	c_addr.sin_family = AF_INET;
        c_addr.sin_port = htons(atoi(argv[2]));
        inet_aton(argv[1],&c_addr.sin_addr);
        connect(c_fd, (struct sockaddr *)&c_addr, sizeof(struct sockaddr_in));	
	//printf("==============连接成功==============\n");
	pid = fork();
	if(pid > 0){
		while(1){
			memset(recvbuf,0,sizeof(recvbuf));
			read(c_fd,recvbuf, 128);
	 		if(strstr(recvbuf,"client quit") != NULL){
				printf("==============成功退出==============\n");	
				exit(0);
			}
			printf("服务端: %s",recvbuf);	
		}
	}
	else if(pid == 0){
		while(1){
			memset(sendbuf,0,sizeof(sendbuf));
			fgets(sendbuf,128,stdin);
			write(c_fd,sendbuf, strlen(sendbuf));
			if(strstr(sendbuf,"quit") != NULL){	
				exit(0);
			}
		}
	}
	close(c_fd);		
	return 0;
}

四、UDP demo

服务端

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

int main(int argc, char* argv[])
{
    int s_fd;
	char sendbuf[128]; 
	char recvbuf[128];
    socklen_t len;
    struct sockaddr_in s_addr,c_addr;
    
	//1.socket
    s_fd = socket(AF_INET, SOCK_DGRAM, 0);
	if(s_fd == -1){
		perror("socket");
		exit(-1);
	}
	
	//2.bind
    memset(&s_addr, 0, sizeof(s_addr));
  	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(atoi(argv[2]));
	inet_aton(argv[1],&s_addr.sin_addr);
    bind(s_fd, (struct sockaddr*)&s_addr, sizeof(s_addr));

	len = sizeof(struct sockaddr_in);
    while(1){ 
    
		//3.recvfrom      	
		memset(recvbuf, 0, sizeof(recvbuf));	
        recvfrom(s_fd, recvbuf, 128, 0, (struct sockaddr*)&c_addr, &len); 
		if(strstr(recvbuf,"quit") != NULL){
			printf("==============客户端已退出==============\n");			
		}else{
			printf("client:%s",recvbuf);    
    	}
    	
		//4.sendto
		memset(sendbuf, 0, sizeof(sendbuf));
		fgets(sendbuf,128,stdin);
		if(strstr(sendbuf,"quit") != NULL){
			printf("==============服务端已退出==============\n");			
			break;
		}
        sendto(s_fd, sendbuf, strlen(sendbuf), 0, (struct sockaddr*)&c_addr, len);
    }
    
	close(s_fd);
	return 0;
}

客户端

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

int main(int argc, char* argv[])
{
	int c_fd;
	char sendbuf[128];
	char recvbuf[128];
	socklen_t len;
    struct sockaddr_in s_addr,c_addr;
	
	//1.socket
    c_fd = socket(AF_INET, SOCK_DGRAM, 0);
    
    memset(&s_addr, 0, sizeof(s_addr));
   	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(atoi(argv[2]));
	inet_aton(argv[1],&s_addr.sin_addr);
	printf("==============连接成功==============\n");
	len = sizeof(struct sockaddr_in);
	
    while(1){
    
		//2.sendto
		memset(sendbuf, 0, sizeof(sendbuf));
		fgets(sendbuf,128,stdin);
        sendto(c_fd, sendbuf, strlen(sendbuf), 0, (struct sockaddr*)&s_addr, len);
		if(strstr(sendbuf,"quit") != NULL){
			printf("==============成功退出==============\n");			
			break;
		}
		
		//3.recvfrom
        	memset(recvbuf, 0, sizeof(recvbuf));
        	recvfrom(c_fd, recvbuf, 128, 0, (struct sockaddr*)&c_addr, &len); 
        	printf("server:%s",recvbuf);
     }

    close(c_fd);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值