学习socket通信总结(一)

最近一直在用linux,很早就想学习linux网络编程。

今天刚好抽出一段时间,学习了简单的socket通信,写了一个简单的客户端/服务器通信代码。现在将今天学习的内容做一个总结。

一、相关概念说明

Socket起源于Unix,而Unix基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。Socket就是该模式的一个实现,网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用:Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。(摘自网络https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/08.1.md)

二、常用数据类型

struct sockaddr
{
    sa_family_t sa_family;
    char sa_data[14];
};
struct sockaddr_in
{
    sa_family_t sin_family;   //地址族: AF_INET
    u_int16_t  sin_port;         //端口号:用网络字节序表示
    struct in_addr sin_addr;  //IPv4地址结构体
};


三、常用函数介绍

1.创建socket

int socket (int domain, int type, int protocol);
参数介绍:domain协议族、type指定服务类型、protocol在前两个参数构成的协议族集合下,选择一个具体的协议,一般为0。

2.命名socket

int bind (int fd, const struct sockaddr* addr, socklen_t len);

将socket和socket地址绑定到一起

参数介绍:fd句柄(文件描述符),addr协议(socket地址),len长度

3.监听socket

int listen(int sockfd, int backlog);
参数介绍:backlog参数提示内核监听队列的最大长度,即可以最大连接数量。

4.接受连接

int accept (int fd, struct sockaddr* addr, socklen_t * addr_len);

需注意,这里的addr为一个新的socket地址,用于存放接受到的连接信息。

5.发起连接
int connect (int fd, const struct sockaddr* addr, socklen_t len);
 
  


6.关闭连接

int close(int fd);

7.读写操作

发送接收,读写

recv,send,read,write。

四、简单例子

客户端

#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
	char buf[256] = "hello";
	int recbytes = 0;
	int i = 5;
	struct sockaddr_in saddr;
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if ( -1 == sockfd )
	{
		printf("socket failed!\n");
		return -1;
	}
	printf("socket success!\n");
	memset(&saddr, 0, sizeof(struct sockaddr_in));
	saddr.sin_family = AF_INET;
	saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	saddr.sin_port = htons(5500);

	if( -1 == connect(sockfd, (struct sockaddr *)(&saddr), sizeof(struct sockaddr)) )
	{
		printf("connect failed\n");
		return -1;
	}
	printf("connect success!\n");

	while(i)
	{
//		int res = send(sockfd, buf, 255, 0);
//		if( -1 == res )
//		{
//			printf("send failed!\n");
//			return -1;
//		}
//		printf("send success\n");
		if( -1 == write(sockfd, "hello", 32))
		{
			printf("write failed\n");
			return -1;
		}
		printf("write success\n");
		i -= 1;
	}
	close(sockfd);
	return 0;
}


服务端

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
	int nfp;
	char buf[256] = {0};
	int recbytes = 0;
	struct sockaddr_in saddr, caddr;
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if ( -1 == sockfd )
	{
		printf("socket failed!\n");
		return -1;
	}
	printf("socket success!\n");
	memset(&saddr, 0, sizeof(struct sockaddr_in));
	saddr.sin_family = AF_INET;
	saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	saddr.sin_port = htons(5500);

	if( -1 == bind(sockfd, (struct sockaddr *)(&saddr), sizeof(struct sockaddr)))
	{
		printf("bind failed!\n");
		return -1;
	}
	printf("bind success!\n");

	if( -1 == listen(sockfd,5))
	{
		printf("listen failed!\n");
		return -1;
	}
	printf("listen success!\n");

	recbytes = sizeof(struct sockaddr_in);
	nfp = accept(sockfd, (struct sockaddr *)(&caddr), &recbytes);
	if( -1 == nfp )
	{
		printf("accept failed\n");
		return -1;
	}
	printf("accept success\n");

	while(1)
	{
		buf[0] = '\0';
//		int res = recv(nfp, buf, 255, 0);
//		if( -1 == res )
//		{
//			perror("");
//			printf("recv error!\n");
//			return -1;
//		}
//		if( 0 == res )
//		{
//			printf("recv ok!\n");
//			return 0;
//		}
//		recbytes = strlen(buf);
//		buf[recbytes] = '\0';
//		printf("%s\n", buf);
//
		recbytes = read(nfp, buf, 255);
		if( -1 == recbytes )
		{
			printf("read data failed\n");
			perror("");
			return -1;
		}
		if( 0 == recbytes )
		{
			printf("read ok!\n");
			return 0;
		}
		printf("read data success!\n");
		buf[recbytes] = '\0';
		printf("%s\n", buf);

	}
	getchar();
	close(sockfd);
	return 0;
}

先介绍这么多,下次有时间在继续学习socket编程。

如果有什么问题,可以联系我,共同学习。

你可能感兴趣的:(c语言)