基于Socket实现一对一通信1_第1页
基于Socket实现一对一通信1_第2页
基于Socket实现一对一通信1_第3页
基于Socket实现一对一通信1_第4页
基于Socket实现一对一通信1_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Linux下的Socket编程实现一对一通信 田昕煜 (1.通信工程,13081405)摘要: 以当下社会普遍应用QQ,微信,微博等聊天工具为引,设计了简单的Linux系统下的socket编程实现客户端与服务器的一对一通信。关键词: 多线程,socket创建,bind函数,connect函数,listen函数,accept函数,数据传输0 基本原理本聊天室程序在 Ubuntu 下,采用 C 语言实现,结构为 Client/Server 结构;服务端程序通过共享存储区存储聊天数据,并发送给每个连接的客户端;服务端程序和客户端程序都是通过父子进程分别负责发送和接收数据的,以避免数据冲撞;1设计思路

2、及功能1.1 总体设计框架1.2程序设计方案Socket创建 socket函数原型为: #include #include int socket(int domain, int type, int protocol); 功能:调用成功,返回socket文件描述符;失败,返回1,并设置errno 参数说明: domain指明所使用的协议族,通常为PF_INET,表示互联网协议族(TCP/IP协议 族; type参数指定socket的类型: SOCK_STREAM 提供有序、可靠、双向及基于连接的字节流 SOCK_DGRAM 支持数据报 SOCK_SEQPACKET 提供有序、可靠、双向及基于连接

3、的数据报通信 SOCK_RAW 提供对原始网络协议的访问 SOCK_RDM 提供可靠的数据报层,但是不保证有序性 protocol通常赋值0. socket描述符是一个指向内部数据结构的指针,它指向描述符表入口。调用socket函数时,socket执行体将建立一个socket,实际上建立一个socket意味着为一个socket数据结构分配存储空间。socket执行体为你管理描述符表。 两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。socket数据结构中包含这五种信息。Socket绑定 bind函数原型为: #include #in

4、clude int bind(int sock_fd,struct sockaddr *my_addr, int addrlen); 功能说明:将套接字和指定的端口相连。成功返回0,否则,返回1,并置errno. 参数说明:sock_fd是调用socket函数返回的socket描述符, my_addr是一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针; addrlen常被设置为sizeof(struct sockaddr)。 struct sockaddr结构类型是用来保存socket信息的: struct sockaddr unsigned short sa_family

5、; /* 地址族, AF_xxx */ char sa_data14; /* 14 字节的协议地址 */ ; sa_family一般为AF_INET,代表Internet(TCP/IP)地址族; sa_data则包含该socket的IP地址和端口号。 另外还有一种结构类型: struct sockaddr_in short int sin_family; /* 地址族 */ unsigned short int sin_port; /* 端口号 */ struct in_addr sin_addr; /* IP地址 */ unsigned char sin_zero8; /* 填充0 以保持与

6、struct sockaddr同样大小 */ ; 这个结构更方便使用。sin_zero用来将sockaddr_in结构填充到与struct sockaddr同样的长度,可以用bzero()或memset()函数将其置为零。指向sockaddr_in 的指针和指向sockaddr的指针可以相互转换,这意味着如果一个函数所需参数类型是sockaddr时,你可以在函数调用的时候将一个指向 sockaddr_in的指针转换为指向sockaddr的指针;或者相反。 使用bind函数时,可以用下面的赋值实现自动获得本机IP地址和随机获取一个没有被占用的端口号: my_addr.sin_port = 0;

7、/* 系统随机选择一个未被使用的端口号 */ my_addr.sin_addr.s_addr = INADDR_ANY; /* 填入本机IP地址 */ 通过将my_addr.sin_port置为0,函数会自动为你选择一个未占用的端口来使用。同样,通过将my_addr.sin_addr.s_addr置为INADDR_ANY,系统会自动填入本机IP地址。 注意在使用bind函数是需要将sin_port和sin_addr转换成为网络字节优先顺序。 计算机数据存储有两种字节优先顺序:高位字节优先和低位字节优先(大端和小端)。Internet上数据以高位字节优先顺序在网络上传输,所以对于在内部是以低位字

8、节优先方式存储数据的机器,在Internet上传输数据时就需要进行转换,否则就会出现数据不一致。 Bind()函数在成功被调用时返回0;出现错误时返回-1并将errno置为相应的错误号。 需要注意的是,在调用bind函数时一般不要将端口号置为小于1024的值,因为1到1024是保留端口号,你可以选择大于1024中的任何一个没有被占用的端口号。连接 面向连接的客户程序使用connect函数来配置socket并与远端服务器建立一个TCP连接,其函数原型为: #include #include int connect(int sock_fd, struct sockaddr *serv_addr,i

9、nt addrlen); 功能说明:客户端发送服务请求。成功返回0,否则返回1,并置errno。 参数说明:sock_fd 是socket函数返回的socket描述符;serv_addr是包含远端主机IP地址和端口号的指针;addrlen是远端地质结构的长度。 进行客户端程序设计无须调用bind(),因为这种情况下只需知道目的机器的IP地址,而客户通过哪个端口与服务器建立连接并不需要关心, socket执行体为你的程序自动选择一个未被占用的端口,并通知你的程序数据什么时候到端口。 connect函数启动和远端主机的直接连接。只有面向连接的客户程序使用socket时才需要将此socket与远端主

10、机相连。无连接协议从不建立直接连接。面向连接的服务器也从不启动一个连接,它只是被动的在协议端口监听客户的请求。监听 listen函数使socket处于被动的监听模式,并为该socket建立一个输入数据队列,将到达的服务请求保存在此队列中,直到程序处理它们。 int listen(int sock_fd, int backlog); 功能说明:等待指定的端口的出现客户端连接。调用成功返回0,否则,返回1,并置errno. 参数说明:sock_fd 是socket系统调用返回的socket 描述符; backlog指定在请求队列中允许的最大请求数,进入的连接请求将在队列中等待accept()接受

11、accept()函数让服务器接收客户的连接请求。在建立好输入队列后,服务器就调用accept函数,然后睡眠并等待客户的连接请求。 int accept(int sock_fd, void *addr, int *addrlen); 功能说明:用于接受客户端的服务请求,成功返回新的套接字描述符,失败返回1,并置errno。 参数说明:sock_fd是被监听的socket描述符,addr通常是一个指向sockaddr_in变量的指针,该变量用来存放提出连接请求服务的主机的信息(某台主机从某个端口发出该请求);addrten通常为一个指向值为sizeof(struct sockaddr_in)的整型

12、指针变量。出现错误时accept函数返回-1并置相应的errno值。 首先,当accept函数监视的 socket收到连接请求时,socket执行体将建立一个新的socket,执行体将这个新socket和请求连接进程的地址联系起来,收到服务请求的初始socket仍可以继续在以前的 socket上监听,同时可以在新的socket描述符上进行数据传输操作。结束传输 当所有的数据操作结束以后,你可以调用close()函数来释放该socket,从而停止在该socket上的任何数据操作: 2关键代码解释客户端: #include #include #include #include #include #

13、include #include #define LISTEN_LEN 10int err,sd;char rd_buf100, wr_buf100;void *thread_read1(void *arg)while(1)memset(rd_buf,0,100);read(sd,rd_buf,100);printf(%sn,rd_buf);sleep(2);return NULL;void *thread_write1(void *arg)while(1)memset(wr_buf, 0, 100);scanf(%s, wr_buf);write(sd,wr_buf,sizeof(wr_bu

14、f);sleep(2);return NULL;int main()pthread_t tid1,tid2;int server_len,client_len;struct sockaddr_in server_ip,client_ip;sd = socket(AF_INET,SOCK_STREAM,0);if(sd 0)printf(socket failed! errno = %dn,errno);close(sd);return -1;server_ip.sin_family = AF_INET;server_ip.sin_port = htons(5678);server_ip.sin

15、_addr.s_addr = htonl(INADDR_ANY);memset(server_ip.sin_zero,0,8); err = connect(sd,(struct sockaddr *)(&server_ip),sizeof(struct sockaddr);if(err 0)printf(connect failed! errno = %dn,errno);close(sd);return -1;err = pthread_create(&tid1,NULL,thread_read1,NULL);if(err != 0)printf(thread_read1 creat fa

16、iled! errno = %dn,errno);close(sd);return -1;err = pthread_create(&tid2,NULL,thread_write1,NULL);if(err != 0)printf(thread_write1 creat failed! errno = %dn,errno);close(sd);return -1;pthread_join(tid1,NULL);pthread_join(tid2,NULL);close(sd);return 0 ; 服务器:#include #include #include #include #include

17、 #include #include #define LISTEN_LEN 10int i=0,err,sd,ad;char buf12100,buf21100;void *thread_read1(void *arg);void *thread_write1(void *arg);void *thread_read1(void *arg)while(1)read(ad,buf12,100);printf(%sn, buf12);sleep(2);return NULL;void *thread_write1(void *arg)while(1)memset(buf21, 0, 100);sc

18、anf(%s, buf21);write(ad,buf21,100);sleep(2);return NULL;int main()pthread_t tid1,tid2;int server_len,client_len;struct sockaddr_in server_ip,client_ip;sd = socket(AF_INET,SOCK_STREAM,0);if(sd 0)printf(socket failed! errno = %dn,errno);close(sd);return -1;server_ip.sin_family = AF_INET;server_ip.sin_

19、port = htons(5678);server_ip.sin_addr.s_addr = htonl(INADDR_ANY);memset(server_ip.sin_zero,0,8); err = bind(sd,(struct sockaddr *)(&server_ip),sizeof(struct sockaddr);if(err 0)printf(bind failed! errno = %dn,errno);close(sd);return -1;err = listen(sd,LISTEN_LEN);if(err 0)printf(listen failed! errno

20、= %dn,errno);close(sd);return -1;client_len = sizeof(struct sockaddr);while(1)ad = accept(sd,(struct sockaddr *)(&client_ip),&client_len);if(ad 0 )printf(accept failed! errno = %dn,errno);close(sd);return -1;err = pthread_create(&tid1,NULL,thread_read1,NULL);if(err != 0)printf(thread_read1 creat failed! errno = %dn,errno);close(sd);close(ad);return -1;err = pthread_create(&tid2,NULL,thread_write1,NULL);if(err != 0)printf(thread_write1 creat f

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论