linux socket编程

                                                    socket 网络编程编程

       复习了两天的socket网络编程,打算做个总结,学过看过网络通信技术相关书籍就知道网络通信的的基础,TCP/IP为一组协议族,有两种模型结构为OSI模型及其简化模型tcp/ip模式,OSI模型多了两层分别为会话层,和表示层, tcp/ip模型有五层,应用层,传输层,网络层,数据链路层,及物理层。应用层协议有telent,和ftp,http等,网络层为ip协议,传输层有主要有两种传输协议,tcp和udp传输两种,两种各有优缺点,tcp可靠,但是效率低,udp高效率,但不可靠,要使用须得根据具体情况而定,至于其他层打算要是忘记了打算让自己看书即可,应用程的一般都是写好了的应用程序,我们只需要进行相应的移植与安装即可,可以去研究源码。

经观察发现tcp的传输模型与udp传输模型只有一小点区别,一个是链接的,一个是不链接的,socket编程一般要用到以下几个函数,编程直接套用即可。

服务端:

第一步:

socket( int af, int type, int protocol)函数有三个参数:

 af:一个地址描述。目前仅支持AF_INET格式,也就是说ARPA Internet地址格式。

 type:新套接口的类型描述。 ,一般用SOCK_STREAM表示双向直接流,前提是必须处于链接状态,一般用于tcp,udp用SOCK_DGRAM

    protocol:套接口所用的协议。如调用者不想指定,可用0指定,表示缺省。

   其次函数带返回值,可以用以判断是否创建字节流创建成功,如果大于0其返回值作为connect函数的第一个入口参数值

第二步:在链接客户端发起链接访问之前创立struct sockaddr_in address  address结构;其重要成员如下

 address. sin_family这个参数一般为AF_INET,与socket函数的第一个参数一样,表示ip类为ipv4;

address.sin_addr.s_addr 这个为服务器地址,一般客户端设置成服务器地址,服务端设置成0.0.0.0表示能监听任何的ip地址的访问,为127.0.0.1表示本机地址,也就是会换地址,这两个试验过。可行,以实现局域网内的tcp、udpc传输方式。

address.sin_port=htons(9734);端口号记得此端口号客户端与服务端一定是绑定到同一个ip的端口号上。

第三步:bindconnect()listen()调用前使用,int bind( int sockfd , const struct sockaddr * my_addr, socklen_t addrlen);

第一参数:一般为套接字创建成功后的返回值

第二参数:sockaddr:标识一未捆绑套接口的描述字。要是类型不一样用强制转换即可

第三参数:为sockaddr结构体所占长度

第四步:调用listen函数,函数原型int listen( int s, int backlog);

S:用于标识一个已捆绑未连接套接口的描述字。及创建套接字返回成功后的返回值

backlog:等待连接队列的最大长度。

第五步:accept函数原型int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

sockfd:套接字描述符,该套接口在 listen()后监听连接。套接字返回值,
addr:(可选)指针,指向一缓冲区,其中接收为通讯层所知的连接实体的地址。Addr参数的实际格式由套接口创建时所产生的地址族确定。
  要是参数类型不一用强制转换。
addrlen:(可选)指针,输入参数,配合addr一起使用,指向存有addr地址长度的整型数。
其返回值为客户端套接字的返回值,及接受了客户端的链接请求,返回客户端方的套接字标识
第五步:用recv函数接受,send函数发送,具体参数不在阐述

客户端:

       客户端与服务端不同的是客户端只需要创建套接字---------写入与服务端一样的sockaddr_in几个总要成员参数值-------调用connect函数--------,之后再操作
recv与send函数即可

connect()函数:原型: int connect(int s, const struct sockaddr * name, int namelen);

  第一参数:一般为socket函数的返回值

  第二参数:name:指向要连接套接字的sockaddr结构体的指针

 第三参数为  结构体长度用sizeof求得


代码如下:

服务端:

<pre name="code" class="cpp">#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc,char *argv[])
{	
	int server_sockfd,client_sockfd;
	int server_len,client_len;
	struct sockaddr_in server_address;
	struct sockaddr_in client_address;
	int i,byte;
	char char_send,char_recv;
	server_sockfd = socket(AF_INET,SOCK_STREAM,0);//创建
	server_address.sin_family = AF_INET;
	server_address.sin_addr.s_addr = inet_addr("0.0.0.0");//可换成回环地址实验
	server_address.sin_port=htons(9734);
	server_len = sizeof(server_address);
	bind(server_sockfd,(struct sockaddr *)&server_address,server_len); //捆绑套套接字
	listen(server_sockfd,5);                                          //监听
	client_len = sizeof(client_address);
	client_sockfd = accept(server_sockfd,                             //是否接受连接
	(struct sockaddr *)&client_address,(socklen_t *)&(client_len));
		printf("server wait kehu quest connect2\n");
	for(i=0,char_send = '1';i<5;i++,char_send++)
	{
		if((byte=recv(client_sockfd,&char_recv,1,0))==-1)//此处需注意接收函数的参数
		{
			perror("recv");
			exit(EXIT_FAILURE);
		}
		printf("receive from client is %c\n",char_recv);
		if((byte=send(client_sockfd,&char_send,1,0))==-1)
		{
			perror("send");
			exit(EXIT_FAILURE);
		}
	}
		shutdown(client_sockfd,2); //关闭连接函数
		
		shutdown(server_sockfd,2);
		
}


 

客户端:

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

int main(int argc,char *argv[])
{
	int sockfd;                                   
	int len;
	struct sockaddr_in address;
	int result;
	int i,byte;
	char char_send,char_recv;
	printf("server wait kehu quest connect1\n");
	sockfd = socket(AF_INET,SOCK_STREAM,0);   //创建套接字,至于参数查相应手册即可
	if(sockfd<0)//判断套接字创建是否成功,
	{          //这条语句按语法来说其实可以更上一条语句
	          //连着写在一起但是不成功后来我改成这样就行了,不知道为什么,可能是系统原因等          
		printf("socket failure\n");
		exit(0);
	}
	printf("server wait kehu quest connect3\n");
	address.sin_family = AF_INET;                //标识ipv4地址
	address.sin_addr.s_addr = inet_addr("192.168.1.104");//可换成回环地址
	address.sin_port=htons(9734);                       //端口号
	len = sizeof(address);
	result = connect(sockfd,(struct sockaddr *)&address,len);
	 if(result<0)
	{
		printf("connect to failure\n");
		exit(EXIT_FAILURE);//提示代码是否执行函数
	}

	for(i=0,char_send = 'A';i<5;i++,char_send++)
	{
		if((byte=send(sockfd,&char_send,1,0))==-1)
		{
			perror("send");
			exit(EXIT_FAILURE);
		}
		if((byte=recv(sockfd,&char_recv,1,0))==-1)
		{
			perror("recv");
			exit(EXIT_FAILURE);
		}
		printf("receive from server %c\n",char_recv);
	}
		
		close(sockfd);//套接字关闭函数
		exit(0);
		
}
之后又实验了udp,upd没有tcp服务端的listen,accept,即没有监听与等待连接,有bind函数相当于是时时克克都已经在接受状态,还有接受发送函数为recvfrom与sendto两个函数,具体阐述查看手册,udp的两端程序差别不大,感觉都差不多,就难得写了。。。。。。。。。。。。


                                                

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值