【学习笔记】简单的socket网络编程实例

TCP的三次握手(图片来自百度百科)

【学习笔记】简单的socket网络编程实例_第1张图片

TCP的四次分手(图片来自百度百科)

【学习笔记】简单的socket网络编程实例_第2张图片


单向交互套结字

服务端

描述符,sfp接收所有连接请求,然后将每个连接传给对应的一个nfp。类似电话总机与分机。

/* 
* Author:		[email protected]
* 
* Created Time: 2014年03月19日 星期三 17时29分14秒
* 
* FileName:     sock_server.c
* 
* Description:  
*
*/

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

int main(void)
{
	int sfp,nfp;//两个描述符
	struct sockaddr_in server_addr,client_addr;//服务器地址,客户端地址
	int sin_size;//???
	unsigned short portnum = 0x8888;//服务器使用端口

	printf("Here's a socket server\n");
	sfp = socket(AF_INET, SOCK_STREAM,0);
	if(sfp == -1)
	{
		printf("SOCKET FAILED\n");
		exit(1);
	}
	printf("SOCKET SUCCEED\n");

	/*设置监听的端口和IP信息*/
	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(portnum);
	
	/*bind() 端口绑定函数*/
	if(-1 == bind(sfp,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr)))
	{
		printf("BIND FAILED\n");
		exit(1);
	}
	printf("BIND SUCCEED\n");
	
	/*listen 监听端口函数*/
	if(-1 == listen(sfp,5))
	{
		printf("LISTEN FAILED\n");
		exit(1);
	}
	printf("LISTEN SUCCEED\n");

	while(1)
	{
		sin_size = sizeof(struct sockaddr_in);
		/*服务端accept函数,调用即进入阻塞状态,等待用户连接。
		 *在没有用户进行连接时,程序停在此处。
		 *此处accpet的第二个参数用于获取客户端的端口和地址信息。
		 */
		nfp = accept(sfp,(struct sockaddr *)(&client_addr),&sin_size);
		if(nfp == -1)
		{
			printf("ACCEPT FAILED\n");
			exit(1);
		}
		printf("ACCEPT SUCCEED\nSERVER START GET CONNECT FROM %#x\n",ntohl(client_addr.sin_addr.s_addr),ntohs(client_addr.sin_port));
	
		/*函数向客户端使用write函数发送信息,也可以尝试使用其他函数实现*/
		if(-1 == write(nfp,"SOCKET CONNECTED,WELCOME!\n",30));
		{
			printf("WRITE FAILED\n");
			exit(1);
		}
		printf("WRITE SUCCEED\n");
		close(nfp);
	}
	close(sfp);
	return 0;
}


客户端

/* 
* Author:		[email protected]
* 
* Created Time: 2014年03月20日 星期四 18时42分19秒
* 
* FileName:     sock_client.c
* 
* Description:  
*
*/

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

#define LENGTH 1024

int main(void)
{
	int cfd;//文件描述符
	int recbytes;
	int sin_size;
	char buffer[LENGTH]={0};//接受缓冲区
	struct sockaddr_in server_addr,client_addr;//服务器信息,客户端信息
	unsigned short portnum=0x8888;//服务端使用的通信端口,可更改,但必须与服务端保持一致

	printf("here's a socket client\n");
	//建立socket,使用tcp流传输
	cfd = socket(AF_INET,SOCK_STREAM,0);
	if(cfd == -1)
	{
		printf("SOCKET FAILED\n");
		exit(1);
	}
	printf("SOCKET SUCCEED\n");

	//构造服务器端的ip及端口信息
	bzero(&server_addr,sizeof(struct sockaddr_in));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//ip转换为4字节整型,使用时需要根据服务器端ip进行更改
	server_addr.sin_port = htons(portnum);//htons将short转化为网络型,即:将小端数据转化为大端数据(以两字节为单位,首尾交换)
										//一般来说网络为大端,PPC的cpu为大端,x86的cpu为小端,arm可以配置大小端、

	printf("server_addr = %#x, port: %#x\n",server_addr.sin_addr.s_addr,server_addr.sin_port);//打印出小端
	//客户端连接服务端,参数顺序为socket描述符,地址信息,地址结构大小
	
	if(-1 == connect(cfd,(struct sockaddr *)(&server_addr),sizeof(server_addr)))
	{
		printf("CONNECT FAILED\n");
		exit(1);
	}
	printf("CONNECT SUCCEED\n");
	//连接成功,从服务器端接收字符
	if(-1 == (recbytes = read(cfd,buffer,LENGTH)))
	{
		printf("READ FAILED\n");
		exit(1);
	}
	printf("READ SUCCEED\n");

	buffer[recbytes]='\0';
	printf("%s\n",buffer);

	//输入任意字符结束程序
	puts("press any key to end\n");
	getchar();
	close(cfd);//关闭连接
	return 0;
}


双向自由交互套结字

服务端

/* 
* Author:		[email protected]
* 
* Created Time: 2014年03月121日 星期三 17时26分23秒
* 
* FileName:     while_sock_server.c
* 
* Description:  
*
*/

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

#define LENGTH 1024

int main(void)
{
	//write()相关变量
	int sfp,nfp;//两个描述符
	struct sockaddr_in server_addr,client_addr;//服务器地址,客户端地址
	int sin_size;//???
	unsigned short portnum = 8086;//服务器使用端口
	char server_msg[LENGTH];
	char sock_flush;
	
	//read()相关变量
	char buffer[LENGTH];//存储read()收到的信息
	int recbytes;//	计数器,计算buffer收到的字节数

	printf("Here's a socket server\n");
	sfp = socket(AF_INET, SOCK_STREAM,0);
	if(sfp == -1)
	{
		printf("SOCKET FAILED\n");
		exit(1);
	}
	printf("SOCKET SUCCESS\n");

	/*设置监听的端口和IP信息*/
	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(portnum);
	
	/*bind() 端口绑定函数*/
	if(-1 == bind(sfp,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr)))
	{
		printf("BIND FAILED\n");
		exit(1);
	}
	printf("BIND SUCCESS\n");

	/*listen 监听端口函数*/
	if(-1 == listen(sfp,5))
	{
		printf("LISTEN FAILED\n");
		exit(1);
	}
	printf("LISTEN SUCCESS\n");
	
	sin_size = sizeof(struct sockaddr_in);
	/*服务端accept函数,调用即进入阻塞状态,等待用户连接。
	 *在没有用户进行连接时,程序停在此处。
	 *此处accpet的第二个参数用于获取客户端的端口和地址信息。
	 */
	nfp = accept(sfp,(struct sockaddr *)(&client_addr),&sin_size);
	if(nfp == -1)
	{
		printf("ACCEPT FAILED\n");
		exit(1);
	}
	printf("ACCEPT SUCCESS\nSERVER START GET CONNECT FROM %#x\n",ntohl(client_addr.sin_addr.s_addr),ntohs(client_addr.sin_port));

	
	if(fork() == 0)
	{
		/*函数向客户端使用write函数发送信息,也可以尝试使用其他函数实现*/
		//尝试发送消息
		if(-1 == write(nfp,"SOCKET CONNECTED,WELCOME!\n",30))
		{
			printf("WRITE FAILED\n");
			exit(1);
		}
		printf("WRITE SUCCESS\n");

		//write() 发送消息
		while(1)
		{
			gets(server_msg);
			if(-1 == write(nfp,server_msg,strlen(server_msg)))
			{
				printf("WRITE FAILED\n");
				exit(1);
			}
			memset(server_msg,0,strlen(server_msg));
			//while(((sock_flush = getchar()) != '\n') && (sock_flush != EOF));//flush cache
			printf("    【SEND SUCCESS】\n");
		}
		close(nfp);
	}
	else
	{
		//read() 接收信息
		while(1)
		{
			if( (recbytes = read(nfp,buffer,LENGTH)) <= 0)
			{
				break;
			}
			buffer[recbytes]='\0';
			printf("%s\n",buffer);
			printf("    【READ SUCCESS】\n");
		}
		close(nfp);
	}	
	close(sfp);
	
	return 0;
}


客户端

/* 
* Author:		[email protected]
* 
* Created Time: 2014年03月21日 星期四 17时27分36秒
* 
* FileName:     sock_client.c
* 
* Description:  
*
*/

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

#define LENGTH 1024

int main(void)
{
	int cfd;//句柄,文件描述符
	int recbytes;//计数器,计算接收到的字节数
	int sin_size;
	char buffer[LENGTH]={0};//存储read()收到的数据
	char client_msg[LENGTH];//存储write()发送的数据
	struct sockaddr_in server_addr,client_addr;//服务器信息,客户端信息
	unsigned short portnum=8086;//服务端使用的通信端口,可更改,但必须与服务端保持一致

	printf("here's a socket client\n");
	//建立socket,使用tcp流传输
	cfd = socket(AF_INET,SOCK_STREAM,0);
	if(cfd == -1)
	{
		printf("SOCKET FAILED\n");
		exit(1);
	}
	printf("SOCKET SUCCESS\n");

	//构造服务器端的ip及端口信息
	bzero(&server_addr,sizeof(struct sockaddr_in));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//ip转换为4字节整型,使用时需要根据服务器端ip进行更改
	server_addr.sin_port = htons(portnum);//htons将short转化为网络型,即:将小端数据转化为大端数据(以两字节为单位,首尾交换)
										//一般来说网络为大端,PPC的cpu为大端,x86的cpu为小端,arm可以配置大小端、

	printf("server_addr = %#x, port: %#x\n",server_addr.sin_addr.s_addr,server_addr.sin_port);//打印出小端

	//connect连接函数,客户端连接服务端,参数顺序为socket描述符,地址信息,地址结构大小
	if(-1 == connect(cfd,(struct sockaddr *)(&server_addr),sizeof(server_addr)))
	{
		printf("CONNECT FAILED\n");
		exit(1);
	}
	printf("CONNECT SUCCESS\n");

	//分裂进程,分别进行读read()和写write()
	if(fork() == 0)
	{
		//while(strcmp(buffer, "end")!=0)
		while(1)
		{
			if((recbytes = read(cfd,buffer,LENGTH)) <= 0)
			{
				//break;
				exit(0);
			}
			buffer[recbytes]='\0';
			printf("%s\n",buffer);
			printf("    【READ SUCCESS】\n");
		}
		close(cfd);//关闭连接
	}
	else
	{
		//write() 发送消息
		while(1)
		{
			gets(client_msg);
			if(-1 == write(cfd,client_msg,strlen(client_msg)))
			{
				printf("WRITE FAILED\n");
				exit(1);
			}
			memset(client_msg,0,strlen(client_msg));
			//while(((sock_flush = getchar()) != '\n') && (sock_flush != EOF));//flush cache
			printf("    【SEND SUCCESS】\n");
		}
		close(cfd);
	}
	close(cfd);//同步关闭read()与write()
	return 0;
}


参考资料

linux下C语言socket网络编程简例

sockaddr_in结构体构成_百度知道

《linux c编程实战》童永清

你可能感兴趣的:(【学习笔记】简单的socket网络编程实例)