基于linux的socket多线程通信

基于linux的socket多线程通信
基于linux的socket多线程通信

1、网络中进程之间如何通信?

本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类:

?消息传递(管道、FIFO、消息队列)

?同步(互斥量、条件变量、读写锁、文件和写记录

锁、信号量)

?共享内存(匿名的和具名的)

?远程过程调用(Solaris门和Sun RPC)

但这些都不是本文的主题!我们要讨论的是网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的。其实TCP/IP协议族已经帮我们解决了这个问题,网络层的―ip地址‖可以唯一标识网络中的主机,而传输层的―协议+端口‖可以唯一标识主机中的应用程序(进程)。这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。

使用TCP/IP协议的应用程序通常采用应用编程接口:UNIX BSD的套接字(socket)和UNIX System V的TLI(已经被淘汰),来实现网络进程之间的通信。就目前而言,几乎所有的应用程序都是采用socket,而现在又是网络时代,网络中进程通信是无处不在,这就是我为什么说―一切皆socket‖。

2、什么是Socket?

上面我们已经知道网络中的进程是通过socket来通信的,那什么是socket呢?socket起源于Unix,而Unix/Linux基本哲学之一就是―一切皆文件‖,都可以用―打开open –> 读写write/read –> 关闭close‖模式来操作。我的理解就是Socket就是该模式的一个实现,socket 即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭),这些函数我们在后面进行介绍。

socket一词的起源

在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的,撰写者为Stephen Carr、Steve Crocker和Vint Cerf。根据美国计算机历史博物馆的记载,Croker写道:―命名空间的元素都可称为套接字接口。一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定。‖计算机历史博物馆补充道:―这比BSD的套接字接口定义早了大约12年。‖

3、socket的基本操作

既然socket是―open—write/read—close‖模式的一种实现,那么socket就提供了这些操作对应的函数接口。下面以TCP为例,介绍几个基本的socket接口函数。

3.1、socket()函数

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

socket函数对应于普通文件的打开操作。普通文件的打开操作返回一个文件描述字,而socket()用于创建一个socket描述符(socket descriptor),它唯一标识一个socket。这个socket描述字跟文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。

正如可以给fopen的传入不同参数值,以打开不同的文件。创建socket的时候,也可以指定不同的参数创建不同的socket描述符,socket 函数的三个参数分别为:

?domain:即协议域,又称为协议族(family)。常

用的协议族有,AF_INET、AF_INET6、AF_LOCAL

(或称AF_UNIX,Unix域socket)、AF_ROUTE

等等。协议族决定了socket的地址类型,在通信中

必须采用对应的地址,如AF_INET决定了要用ipv4

地址(32位的)与端口号(16位的)的组合、

AF_UNIX决定了要用一个绝对路径名作为地址。

?type:指定socket类型。常用的socket类型有,

SOCK_STREAM、

SOCK_DGRAM、

SOCK_RAW、

SOCK_PACKET、

SOCK_SEQPACKET等等(socket

的类型有哪些?)。

?protocol:故名思意,就是指定协议。常用的协议有,

IPPROTO_TCP、IPPTOTO_UDP、

IPPROTO_SCTP、IPPROTO_TIPC等,它们分别

对应TCP传输协议、UDP传输协议、STCP传输协

议、TIPC传输协议(这个协议我将会单独开篇讨

论!)。

注意:并不是上面的type和protocol可以随意组合的,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。

当我们调用socket创建一个socket时,返回的socket描述字它存在于协议族(address family,AF_XXX)空间中,但没有一个具体的地址。如果想要给它赋值一个地址,就必须调用bind()函数,否则就当调用connect()、listen()时系统会自动随机分配一个端口。

3.2、bind()函数

正如上面所说bind()函数把一个地址族中的特定地址赋给socket。例如对应AF_INET、AF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 函数的三个参数分别为:

?sockfd:即socket描述字,它是通过socket()函数

创建了,唯一标识一个socket。bind()函数就是将

给这个描述字绑定一个名字。

?addr:一个const struct sockaddr *指针,指向要绑

定给sockfd的协议地址。这个地址结构根据地址创

建socket时的地址协议族的不同而不同,如ipv4

对应的是:

?struct sockaddr_in {

? sa_family_t

sin_family; /* address

family: AF_INET */

? in_port_t

sin_port; /* port in

network byte order */

?struct in_addr

sin_addr; /* internet

address */

?};

?

?/* Internet address. */

?struct in_addr {

? uint32_t s_addr;

/* address in network byte

order */

};

ipv6对应的是:

struct sockaddr_in6 {

sa_family_t

sin6_family; /* AF_INET6

*/

in_port_t

sin6_port; /* port

number */

uint32_t

sin6_flowinfo; /* IPv6 flow

information */

struct in6_addr

sin6_addr; /* IPv6

address */

uint32_t

sin6_scope_id; /* Scope ID

(new in 2.4) */

};

struct in6_addr {

unsigned char

s6_addr[16]; /* IPv6

address */

};

Unix域对应的是:

#define UNIX_PATH_MAX

108

struct sockaddr_un {

sa_family_t sun_family;

/* AF_UNIX */

char

sun_path[UNIX_PATH_MAX];

/* pathname */

};

addrlen:对应的是地址的长度。

通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客

户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。

网络字节序与主机字节序

主机字节序就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。

引用标准的Big-Endian和Little-Endian的定义如下:

a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

网络字节序:4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序。由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。字节序,顾名思义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序,一个字节的数据没有顺序的问题了。

所以:在将一个地址绑定到socket的时候,请先将主机字节序转换成为网络字节序,而不要假定主机字节序跟网络字节序一样使用的是

Big-Endian。由于这个问题曾引发过血案!公司项目代码中由于存在这个问题,导致了很多莫名其妙的问题,所以请谨记对主机字节序不要做任何假定,务必将其转化为网络字节序再赋给socket。

3.3、listen()、connect()函数

如果作为一个服务器,在调用socket()、bind()之后就会调用listen()来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求。

int listen(int sockfd, int backlog);

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数。socket()函数创建的socket

默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。

connect函数的第一个参数即为客户端的socket描述字,第二参数为服务器的socket地址,第三个参数为socket地址的长度。客户端通过调用connect函数来建立与TCP服务器的连接。

3.4、accept()函数

TCP服务器端依次调用socket()、bind()、listen()之后,就会监听指定的socket地址了。TCP客户端依次调用socket()、connect()之后就想TCP服务器发送了一个连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数取接收请求,这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作。

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); accept函数的第一个参数为服务器的socket描述字,第二个参数为指向struct sockaddr *的指针,用于返回客户端的协议地址,第三个参数为协议地址的长度。如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与返回客户的TCP连接。

注意:accept的第一个参数为服务器的socket描述字,是服务器开始调用socket()函数生成的,称为监听socket描述字;而accept函数返回的是已连接的socket描述字。一个服务器通常通常仅仅只创建一个监听socket描述字,它在该服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字,当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭。

3.5、read()、write()等函数

万事具备只欠东风,至此服务器与客户已经建立好连接了。可以调用网络I/O进行读写操作了,即实现了网咯中不同进程之间的通信!网络I/O操作有下面几组:

?read()/write()

?recv()/send()

?readv()/writev()

?recvmsg()/sendmsg()

?recvfrom()/sendto()

我推荐使用recvmsg()/sendmsg()函数,这两个函数是最通用的I/O函数,实际上可以把上面的其它函数都替换成这两个函数。它们的声明如下:

#include

ssize_t read(int fd, void *buf, size_t count);

ssize_t write(int fd, const void *buf, size_t count);

#include

#include

ssize_t send(int sockfd, const void*buf, size_t len, int flags); ssize_t recv(int sockfd, void *buf, size_t len, int flags);

ssize_t sendto(int sockfd, const void*buf, size_t len, int flags,

const struct sockaddr *dest_addr, socklen_t addrlen);

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,

struct sockaddr *src_addr, socklen_t *addrlen);

ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0表示已经读到文件的结束了,小于0表示出现了错误。如果错误为EINTR说明读是由中断引起的,如果是ECONNREST表示网络连接出了问题。

write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数。失败时返回-1,并设置errno变量。在网络程序中,当我们向套接字文件描述符写时有俩种可能。1)write的返回值大于0,表示写了部分或者是全部的数据。2)返回的值小于0,此时出现了错误。我们要根据错误类型来处理。如果错误为EINTR表示在写的时候出现了中断错误。如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接)。

其它的我就不一一介绍这几对I/O函数了,具体参见man文档或者baidu、Google,下面的例子中将使用到send/recv。

3.6、close()函数

在服务器与客户端建立连接之后,会进行一些读写操作,完成了读写操作就要关闭相应的socket描述字,好比操作完打开的文件要调用fclose关闭打开的文件。

#include

int close(int fd);

close一个TCP socket的缺省行为时把该socket标记为以关闭,然后立即返回到调用进程。该描述字不能再由调用进程使用,也就是说不能再作为read或write的第一个参数。

注意:close操作只是使相应socket描述字的引用计数-1,只有当引用计数为0的时候,才会触发TCP客户端向服务器发送终止连接请求。

下面为调试正确的客户端与服务器的程序代码:欢迎参考引用:

//server.c:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define MAXLINE 4096

void *rec_data(void *fd)

{

int client_sockfd;

int n;

char buff[4096]={0};

client_sockfd=*((int*)fd);

for(;;)

char buff[4096]={0};

if((n=recv(client_sockfd,buff,MAXLINE,0)) <= 0)

{

printf("recv failed!");

return 0;

}

if(strncmp("quit",buff,4)==0)//接收到quit时,跳出循环

{

printf("you are going to quit\n");

break;

}

printf("From client =>: %s\n",buff);//打印收到的数据

}

free(fd);

close(client_sockfd);

}

int main(int argc,char **argv)

{

int server_sockfd; /*定义一个用于监听的套接字描述符*/

int *client_sockfd; /*定义响应套接字描述符指针变量*/

struct sockaddr_in server_address;/*三种表示套接字地址的结构之一:sockaddr_in结构,专门针对Internet通信域,

存储套接字相关的网络地址信息,例如IP地址,传输层端口号等信息*/

struct sockaddr_in client_address;

int server_len,client_len;

char buff[4096]={0};

/*创建套接字:流式套接字,提供全双工的面向连接的可靠的按序递交的无重复字节流通信;

创建socket过程就是创建一个套接字并返回一个整型描述符*/

server_sockfd = socket(AF_INET,SOCK_STREAM,0);// 创建一个用于监听的流式套接字*/ if(server_sockfd == -1)

{

printf("create socket error!\n");

exit(1);

memset(&server_address, 0, sizeof(server_address));

server_address.sin_family = AF_INET;

server_address.sin_addr.s_addr = htonl(INADDR_ANY);

server_address.sin_port = htons(6666);

/*绑定:往往在生成套接字的描述符后,要将套接字与计算机上的特定的IP地址和传输层端口号相关联,

这个过程称为绑定。一个套接口要使用一个确定的三元组网络地址信息,才能使它在网络中唯一地被标识。

将本地地址绑定到监听套接字*/

if( bind(server_sockfd, (struct sockaddr*)&server_address, sizeof(server_address)) == -1) {

printf("bind socket error!\n");

exit(1);

}

//开始监听,并指定监听套接字请求队列的长度10

if( listen(server_sockfd, 10) == -1)

{

printf("listen socket error!\n");

exit(1);

}

printf("===server waiting for connect===\n");

/* 服务器主循环: 接受和处理来自客户端的连接请求*/

while(1)

{

pthread_t thread;//创建不同的子线程以区别不同的客户端

client_sockfd = malloc(sizeof(*client_sockfd)); //malloc返回的是一个(void *)类型

if(client_sockfd==NULL)

{

printf("malloc failed!");

exit(1);

}

client_len = sizeof(client_address);

/* 接受客户端连接请求,并生成响应套接字*/

*client_sockfd = accept(server_sockfd,(struct sockaddr *)&client_address, (socklen_t *)&client_len);

if(client_sockfd == -1)

{

printf("accept failed!");

exit(1);

}

else

{

printf("\nConnection from => %s,port => %d:\n",inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port));

}

if((pthread_create(&thread, NULL, rec_data, client_sockfd))!=0)//创建子线程

{

printf("pthread_create failed!");

break;

}

}

free(client_sockfd);

close(*client_sockfd);

close(server_sockfd);

exit(1);

}

//client.c

#include

#include

#include

#include

#include

#include

#include

#define MAXLINE 4096

int main(int argc, char** argv)

int sockfd; //sockfd:客户端的套接字描述符

char send_buff[MAXLINE]={0}; //定义一个存放发送数据的数组并进行初始化struct sockaddr_in server_address; //存放服务器端网络地址的结构

if( argc != 2)

{

printf("usage: ./client \n"); //用法:文件名服务器IP地址

exit(1);

}

//创建套接字

if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)

{

printf("create socket error!\n");

exit(1);

}

memset(&server_address, 0, sizeof(server_address));

server_address.sin_family = AF_INET;

server_address.sin_port = htons(6666);

//IP地址转换,点分十进制转换为整数

if( inet_pton(AF_INET, argv[1], &server_address.sin_addr) == -1)

{

printf("inet_pton error for %s\n",argv[1]);

exit(1);

}

//请求建立连接

if( connect(sockfd, (struct sockaddr*)&server_address, sizeof(server_address)) < 0) {

printf("connect error!\n");

exit(1);

}

printf("client send message to server: \n");

while(1)

{

//输入信息

char send_buff[MAXLINE]={0};

scanf("%s",send_buff);

//向套接字发送信息

if( send(sockfd, send_buff, strlen(send_buff), 0) <= 0)

{

printf("send msg error!\n");

exit(1);

}

//添加一个发送结束语句

if(strncmp("quit",send_buff,4)==0)//接收到quit时,跳出循环

{

printf("I am going to quit!\n");

break;

}

}

close(sockfd);

exit(0);

}

Linux下基于socket的文件传输程序设计课程报告

Linux高级开发 课程设计报告 课程设计题目:Linux下基于socket的文件传输程序设计 学院:________信息工程学院_____________ 专业班级:________网络工程_____________ 年级:________级_____________________ 姓名:____________________________ 学号:________201______________ 完成时间:___2015___年____12___月_____25__日 成绩:__________________________________ 指导教师:____________________________

项目分 值 优秀 (100>x≥90) 良好 (90>x≥80) 中等 (80>x≥70) 及格 (70>x≥60) 不及格 (x<60) 评 分参考标准参考标准参考标准参考标准参考标准 学习态度15 学习态度认 真,科学作风 严谨,严格保 证设计时间并 按任务书中规 定的进度开展 各项工作 学习态度比较 认真,科学作 风良好,能按 期圆满完成任 务书规定的任 务 学习态度 尚好,遵守 组织纪律, 基本保证 设计时间, 按期完成 各项工作 学习态度尚 可,能遵守组 织纪律,能按 期完成任务 学习马虎, 纪律涣散, 工作作风 不严谨,不 能保证设 计时间和 进度 技术水平 与实际能力25 设计合理、理 论分析与计算 正确,实验数 据准确,有很 强的实际动手 能力、经济分 析能力和计算 机应用能力, 文献查阅能力 强、引用合理、 调查调研非常 合理、可信 设计合理、理 论分析与计算 正确,实验数 据比较准确, 有较强的实际 动手能力、经 济分析能力和 计算机应用能 力,文献引用、 调查调研比较 合理、可信 设计合理, 理论分析 与计算基 本正确,实 验数据比 较准确,有 一定的实 际动手能 力,主要文 献引用、调 查调研比 较可信 设计基本合 理,理论分析 与计算无大 错,实验数据 无大错 设计不合 理,理论分 析与计算 有原则错 误,实验数 据不可靠, 实际动手 能力差,文 献引用、调 查调研有 较大的问 题 创新10 有重大改进或 独特见解,有 一定实用价值 有较大改进或 新颖的见解, 实用性尚可 有一定改 进或新的 见解 有一定见解观念陈旧 论文(计算 书、图纸)撰写质量50 结构严谨,逻 辑性强,层次 清晰,语言准 确,文字流畅, 完全符合规范 化要求,书写 工整或用计算 机打印成文; 图纸非常工 整、清晰 结构合理,符 合逻辑,文章 层次分明,语 言准确,文字 流畅,符合规 范化要求,书 写工整或用计 算机打印成 文;图纸工整、 清晰 结构合理, 层次较为 分明,文理 通顺,基本 达到规范 化要求,书 写比较工 整;图纸比 较工整、清 晰 结构基本合 理,逻辑基本 清楚,文字尚 通顺,勉强达 到规范化要 求;图纸比较 工整 内容空泛, 结构混乱, 文字表达 不清,错别 字较多,达 不到规范 化要求;图 纸不工整 或不清晰 指导教师评定成绩: 指导教师签名:年月日

Linux下的Socket网络编程:一个简易聊天室的实现-徐慧军

Linux下的Socket网络编程:一个简易聊天室的实现-徐慧军

高级程序设计与应用实践 报告 一个简易聊天室的实现 姓名:徐慧军 学号:2121134 专业:电子与通信工程 学院:信息科学与技术学院 任课教师:廖晓飞 2013年05月02日

Linux下的Socket网络编程: ——一个简易聊天室的实现一、socket介绍 socket接口是TCP/IP网络的API,socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。要学Internet上的TCP/IP 网络编程,必须理解socket接口。 socket接口设计者最先是将接口放在Unix操作系统里面的。如果了解Unix 系统的输入和输出的话,就很容易了解socket了。网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符。socket也具有一个类似于打开文件的函数调用socket(),该函数返回一个整型的socket描述符,随后的连接建立、数据传输等操作都是通过该socket实现的。常用的socket类型有两种:流式socket (SOCK_STREAM)和数据报式socket(SOCK_DGRAM)。流式是一种面向连接的socket,针对于面向连接的TCP服务应用;数据报式socket是一种无连接的socket,对应于无连接的UDP服务应用。 二、Socket创建 socket函数原型为: #include #include int socket(int domain, int type, int protocol); 功能:调用成功,返回socket文件描述符;失败,返回-1,并设置errno 参数说明: domain指明所使用的协议族,通常为PF_INET,表示互联网协议族(TCP/IP 协议族; type参数指定socket的类型: SOCK_STREAM 提供有序、可靠、双向及基于连接的字节流

基于Linux下的Socket通信(操作系统课程设计)

基于Linux下的socket通信 [开发平台]:LINUX [开发语言]:JA V A [开发工具]:ECLISPE [开发人员]:阚广稳(安徽理工大学计算机学院09-2班) I.系统描述: 本系统含有一个服务器(Server.class)和多个客户端(Clinet.class),可以通过每个客户端查看和下载服务器端共享文件夹中的文件。 II.功能描述: A.查看服务器端共享文件夹列表 操作:在Linux终端下输入java Clinet listfiles。 参数说明:listfiles是固定参数。 结果:列出所有共享文件。 B.下载服务器端共享文件夹中的文件 操作:在Linux终端下输入java Clinet download filename dirpath。 参数说明:download是固定参数,filename是想要下载的文件名,dirpath是下载文件保存的路径。 结果:下载文件filename到地址dirpath。 III.功能分析以及实现: A.问题描述:如何创建可以用于多个客户端连接的服务器? 分析解决:因为JA V A语言提供了对多线程的支持,所以我们可以把服务器设计为多线程的,对于每个客户端的连接单独开一条线程与之交 互。 主要实现代码: 服务器端: ServerSocket serversocket=new ServerSocket(5678); Socket socket; While(true){ Socket=serversocket.accept(); new ServerThread(socket).start(); } Class ServerThread extends Thread{ Socket socket; Public ServerThread(Socket socket){ this.socket=socket; } }

基于linux的socket多线程通信

1、网络中进程之间如何通信? 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: ?消息传递(管道、FIFO、消息队列) ?同步(互斥量、条件变量、读写锁、文件和写记录 锁、信号量) ?共享内存(匿名的和具名的) ?远程过程调用(Solaris门和Sun RPC) 但这些都不是本文的主题!我们要讨论的是网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的。其实TCP/IP协议族已经帮我们解决了这个问题,网络层的―ip地址‖可以唯一标识网络中的主机,而传输层的―协议+端口‖可以唯一标识主机中的应用程序(进程)。这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。 使用TCP/IP协议的应用程序通常采用应用编程接口:UNIX BSD的套接字(socket)和UNIX System V的TLI(已经被淘汰),来实现网络进程之间的通信。就目前而言,几乎所有的应用程序都是采用socket,而现在又是网络时代,网络中进程通信是无处不在,这就是我为什么说―一切皆socket‖。 2、什么是Socket? 上面我们已经知道网络中的进程是通过socket来通信的,那什么是socket呢?socket起源于Unix,而Unix/Linux基本哲学之一就是―一切皆文件‖,都可以用―打开open –> 读写write/read –> 关闭close‖模式来操作。我的理解就是Socket就是该模式的一个实现,socket 即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭),这些函数我们在后面进行介绍。 socket一词的起源 在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的,撰写者为Stephen Carr、Steve Crocker和Vint Cerf。根据美国计算机历史博物馆的记载,Croker写道:―命名空间的元素都可称为套接字接口。一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定。‖计算机历史博物馆补充道:―这比BSD的套接字接口定义早了大约12年。‖ 3、socket的基本操作 既然socket是―open—write/read—close‖模式的一种实现,那么socket就提供了这些操作对应的函数接口。下面以TCP为例,介绍几个基本的socket接口函数。 3.1、socket()函数 int socket(int domain, int type, int protocol); socket函数对应于普通文件的打开操作。普通文件的打开操作返回一个文件描述字,而socket()用于创建一个socket描述符(socket descriptor),它唯一标识一个socket。这个socket描述字跟文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。 正如可以给fopen的传入不同参数值,以打开不同的文件。创建socket的时候,也可以指定不同的参数创建不同的socket描述符,socket 函数的三个参数分别为:

linux下socket编程与实例

一、基本socket函数 Linux系统是通过提供套接字(socket)来进行网络编程的。网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符。socket也有一个类似于打开文件的函数:socket(),调用socket(),该函数返回一个整型的socket的描述符,随后的连接建立、数据传输等操作也都是通过该socket实现。 1、socket函数 syntax: int socket(int domain, int type, int protocol); 功能说明: 调用成功,返回socket文件描述符;失败,返回-1,并设置errno 参数说明: domain指明所使用的协议族,通常为PF_INET,表示TCP/IP协议; type参数指定socket的类型,基本上有三种:数据流套接字、数据报套接字、原始套接字 protocol通常赋值"0"。 两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。socket数据结构中包含这五种信息。 2、bind函数 syntax: int bind(int sock_fd,struct sockaddr_in *my_addr, int addrlen); 功能说明: 将套接字和指定的端口相连。成功返回0,否则,返回-1,并置errno. 参数说明: sock_fd是调用socket函数返回值, my_addr是一个指向包含有本机IP地址及端口号等信息的sockaddr类型的指针; struct sockaddr_in结构类型是用来保存socket信息的: struct sockaddr_in { short int sin_family; unsigned short int sin_port; struct in_addr sin_addr; unsigned char sin_zero[8]; }; addrlen为sockaddr的长度。 3、connect函数 syntax: int connect(int sock_fd, struct sockaddr *serv_addr,int addrlen); 功能说明: 客户端发送服务请求。成功返回0,否则返回-1,并置errno。 参数说明: sock_fd 是socket函数返回的socket描述符;serv_addr是包含远端主机IP地址和端口号的指针;addrlen是结构sockaddr_in的长度。 4、listen函数

Linux下基于socket的文件传输程序设计讲解

课程设计 课程名称Linux下基于socket的文件传输程序设计学生学院信息工程学院 专业班级 学号 学生姓名 指导教师 2013 年12月27日

引言 在互联网已经基本普及的情况下,人们越来越依赖于信息网络。因为互联网的使用,我们可以大大的节省了我们的时间及成本。所以文件、信息的传输已经是人们生活中不可缺少的东西。而现在主流的应用软件都是基于WINDOWS平台上开发运行的。 Linux操作系统本身具有非常高的安全性,不易感染病毒(这是WINDOWS系统所不能比拟的),而且可移植性强,应用于大多数的服务器。所以我们应该多开发出适合人们使用的应用软件,使得Linux更加好的为广大网民使用以保障自身的安全性。 本课设主要介绍在Linux下的文件传输原理及功能,虽然不能与主流传输软件的功能相比,但是却是占用的资源比它要少

·1课设背景分析 这次课程设计的要求是在以Linux为内核的操作系统下,实现多线程文件传输系统功能模块。系统模块分为服务器和客户端两部分,客户端实现对文件的上传、下载和查看服务器默认路径下的文件列表;服务器可以对文件进行管理操作,包括创建、删除和重命名等。 多线程文件传输是一种一对多或者多对多的关系,一般是一个服务器对应着多个客户端。客户端通过socket连接服务器,服务器要为客户端创建一个单独进程(线程)监听每个客户端的请求。 创建好连接之后文件就可以通过流的形式传输。linux内核中为我们提供了两种不同形式的读写流,包括read()、write()和send()、recv()。客户机对文件的查看指令也是通过流传递给服务器,服务器根据请求类型返回不同相应流。 根据socket原理和特点绘画出链接流程图,将客户机与服务器的相互通信划分为不同的模块,每个模块负责独立的功能项。服务器输入指令管理目录下的文件,create filename是创建文件命令,rename oldname newname是删除文命令,delete filename 是删除文件命令,同时监听着客户端的请求;客户端向服务器发送上传、下载和查看请求,从而得到不同的相应,包括将文件下载到当前路径下,从当前路径下上传文件给服务器,列出服务器的文件列表。 ·2网络通信原理及socket简介 2.1网络通信原理(TCP) 国际标准化组织(ISO)在1978年提出开放系统互连参考模型(OSI:open system interconnection reference mode),该模型是设计和描述网络通信的基本框架。OSI采用分层的额结构化技术将通信网络分为7层,从低到高为物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。 TCP/IP参考模型是由美国国防部创建,且发展至今最成功的通信协议模型,与OSI模型对应,它将网络功能分为4层,包括网络接口层、网络层、传输层和应用层,每一层都有对应的协议。在传输层的主要协议是TCP协议和UDP协议。socket连接就是基于TCP协议。TCP是一种可靠地数据传输协议。 它为应用程序提供可靠的通信连接。适合于一次传输大批数据的情况。并适用于要求得到响应的应用程序并通过3次握手。 其数据包头格式为: SYN J SYN K, ACK J+1 ACK K+1

Linux_基于socket的局域网聊天软件的设计与实现

提交日期:2012-06-20 基于socket的局域网聊天软件的设计与实现1.实验目的 《Linux操作系统课程设计B》是一门在课程《Linux操作系统与程序设计B》后独立开设的实验课程。这一门实验课程的开设目的是为了通过学生独立完成一个基于Linux平台的较大型应用程序,巩固课堂上学到的Linux平台上的编程规范、技术和技巧,培养学生的编写较大型程序的能力和提高学生综合应用素质。 本课程设计实验主要围绕Linux平台上主流的基础技术展开,这些技术包括:Linux的进程、线程通信和同步技术;socket网络通信技术等,这些技术可以集中体现并应用在并发程序设计中。通过并发程序的设计与开发,培养学生底层软件开发的能力,并为将来从事UNIX/Linux平台开发、嵌入式开发等相对高端的软件开发工作打下基础。 2.软件功能及模块划分 本软件是一个linux下基于socket的聊天室程序,能让局域网内的用户通过该软件进行简单的文字通信。在此基础上增加了 1.聊天室成员之间的发送私聊信息; 2.当新的成员加入后能自动收取最近一段时间内的聊天上下文; 3.用户能够查看历史聊天记录; 4.软件界面基于Qt实现,图形化界面方便用户操作。 主要模块划分: 服务端: 数据包发送和接受模块,聊天记录数据库读写模块,数据包处理模块,聊天记录查询模块 客户端: 数据包发送和接受模块,数据包处理模块,聊天记录查询模块,用户界面与展示模块

3.设计与实现 3.1系统概述与总体结构 本系统采用CS架构,服务端采用固定的端口通信,每个客户端动态设置端口。客户端启动后向服务端告知自己所使用的端口号,以便可以双向通信,同时服务器负责为每个客户端分配一个唯一的ID(服务器的ID为1) 客户端和服务端以及客户端和客户端之间采用约定的数据格式进行通信,以便接收方可以正确的解析命令和数据。 数据包通用格式定义如下 #define MAX_UDP_SIZE 1000 struct udp_packet{ int type; int senderId; long size; char content[MAX_UDP_SIZE]; }; type:表示该数据包的类型,直接决定content字段的含义 senderId:该数据包的发送者的ID, size:整个数据包的数据长度 content:数据包的内容,其数据格式由type决定。 服务器和客户端接受到数据包后,根据type字段的值来解析content字段的数据,从而作出正确的处理和响应。 所有的数据包类型以及对应的content字段的数据结构全部定义在define.h文件中 [系统总体结构]

Linux下基于socket的文件传输程序设计

课程设计报告 课程设计题目:Linux下基于socket的文件传输程序设计 学院: 专业班级: 年级: 姓名: 学号: 完成时间:年月日 成绩: 指导教师:

课程设计指导教师评定成绩表 项目分 值 优秀 (100>x≥90) 良好 (90>x≥80) 中等 (80>x≥70) 及格 (70>x≥60) 不及格 (x<60) 评 分参考标准参考标准参考标准参考标准参考标准 学习态度15 学习态度认 真,科学作风 严谨,严格保 证设计时间并 按任务书中规 定的进度开展 各项工作 学习态度比较 认真,科学作 风良好,能按 期圆满完成任 务书规定的任 务 学习态度 尚好,遵守 组织纪律, 基本保证 设计时间, 按期完成 各项工作 学习态度尚 可,能遵守组 织纪律,能按 期完成任务 学习马虎, 纪律涣散, 工作作风 不严谨,不 能保证设 计时间和 进度 技术水平 与实际能力25 设计合理、理 论分析与计算 正确,实验数 据准确,有很 强的实际动手 能力、经济分 析能力和计算 机应用能力, 文献查阅能力 强、引用合理、 调查调研非常 合理、可信 设计合理、理 论分析与计算 正确,实验数 据比较准确, 有较强的实际 动手能力、经 济分析能力和 计算机应用能 力,文献引用、 调查调研比较 合理、可信 设计合理, 理论分析 与计算基 本正确,实 验数据比 较准确,有 一定的实 际动手能 力,主要文 献引用、调 查调研比 较可信 设计基本合 理,理论分析 与计算无大 错,实验数据 无大错 设计不合 理,理论分 析与计算 有原则错 误,实验数 据不可靠, 实际动手 能力差,文 献引用、调 查调研有 较大的问 题 创新10 有重大改进或 独特见解,有 一定实用价值 有较大改进或 新颖的见解, 实用性尚可 有一定改 进或新的 见解 有一定见解观念陈旧 论文(计算 书、图纸)撰写质量50 结构严谨,逻 辑性强,层次 清晰,语言准 确,文字流畅, 完全符合规范 化要求,书写 工整或用计算 机打印成文; 图纸非常工 整、清晰 结构合理,符 合逻辑,文章 层次分明,语 言准确,文字 流畅,符合规 范化要求,书 写工整或用计 算机打印成 文;图纸工整、 清晰 结构合理, 层次较为 分明,文理 通顺,基本 达到规范 化要求,书 写比较工 整;图纸比 较工整、清 晰 结构基本合 理,逻辑基本 清楚,文字尚 通顺,勉强达 到规范化要 求;图纸比较 工整 内容空泛, 结构混乱, 文字表达 不清,错别 字较多,达 不到规范 化要求;图 纸不工整 或不清晰 指导教师评定成绩: 指导教师签名:年月日课程设计指导教师评定成绩表

基于Linux的Socket网络编程及性能优化

福建电脑2012年第12期 基于Linux的Socket网络编程及性能优化 马丽洁 (内蒙古电子信息职业技术学院内蒙古呼和浩特010070) 【摘要】:本文主要从Socket的建立、配置、连接、数据传输和结束通信五个方面阐述了基于Linux的Socket网络编程的方法和步骤,最后又从最小化报文传输延迟、最小化系统调用负载、为Bandwidth Delay Product调节tcp窗口、动态优化GNU/linux TCP/IP协议栈四个方面进行性能优化,以使应用程序高效、稳定。 【关键词】:Linux,Socket,网络编程,性能优化 Socket的英文原义是“孔”或“插座”,通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原意那样,象一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电,有的提供110伏交流电,有的则提供有线电视节目。客户软件将插头插到不同编号的插座,就可以得到不同的服务。socket也是一种文件描述符。 1.Socket编程 1.1Socket的建立 为了建立Socket,程式能够调用Socket函数,该函数返回一个类似于文档描述符的句柄。Socket描述符是个指向内部数据结构的指针,他指向描述符表入口。调用Socket函数时,socket执行体将建立一个Socket,实际上"建立一个Socket"意味着为一个Socket数据结构分配存储空间。Socket执行体为您管理描述符表。 两个网络程式之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口。Socket数据结构中包含这五种信息。 1.2Socket的配置 通过socket调用返回一个socket描述符后,在使用socket进行网络传输以前,必须配置该socket。面向连接的socket客户端通过调用Con-nect函数在socket数据结构中保存本地和远端信息。无连接socket的客户端和服务端连同面向连接socket的服务端通过调用bind函数来配置本地信息。 Bind函数将socket和本机上的一个端口相关联,随后您就能够在该端口监听服务请求。 使用bind函数时,能够用下面的赋值实现自动获得本机IP地址和随机获取一个没有被占用的端口号。注意在使用bind函数是需要将sin_port和sin_addr转换成为网络字节优先顺序;而sin_addr则无需转换。 1.3建立连接 面向连接的客户程式使用Connect函数来配置socket并和远端服务器建立一个TCP连接,Connect函数启动和远端主机的直接连接。只有面向连接的客户程式使用socket时才需要将此socket和远端主机相连。无连接协议从不建立直接连接。面向连接的服务器也从不启动一个连接,他只是被动的在协议端口监听客户的请求。 Listen函数使socket处于被动的监听模式,并为该socket建立一个输入数据队列,将到达的服务请求保存在此队列中,直到程式处理他们。 accept()函数让服务器接收客户的连接请求。在建立好输入队列后,服务器就调用accept函数,然后睡眠并等待客户的连接请求。 首先,当accept函数监控的socket收到连接请求时,socket执行体将建立一个新的socket,执行体将这个新socket和请求连接进程的地址联系起来,收到服务请求的初始socket仍能够继续在以前的socket上监听,同时能够在新的socket描述符上进行数据传输操作。 1.4数据传输 Send()和recv()这两个函数用于面向连接的socket上进行数据传输。 Send()函数返回实际上发送出的字节数,可能会少于您希望发送的数据。在程式中应该将send ()的返回值和欲发送的字节数进行比较。当send()返回值和len不匹配时,应该对这种情况进行处 106

Linux C的socket聊天室设计与实现

基于Linux C的socket聊天室 1 系统功能 1.1 支持群聊天。 1. 2 支持向指定用户发送悄悄话功能 。 1. 3 支持不同消息不同颜色显示。 1. 4 用户名为登录的唯一标示,所以不允许重名,客户端登录具有重名检查功能。 1. 5 支持上线下线通知。 1. 6 支持服务器发送系统消息功能。 1. 7 支持登录时检测服务器是否在线。 1. 8 支持服务器下线通知客户端,客户端强行下线。 2 硬件平台 2.1 功能 用来作为对Linux C程序所用软件以及操作系统的安装的载体, 2. 2 特点 计算机的整体配置还算不错,4G内存,500G硬盘,1G独立显卡等,使得运行一般的大游戏都不卡。 2. 3 组成 K43T系列华硕计算机一台,外加键盘一个。

3 软件平台 3.1 操作系统平台 主要有Windows7操作系统和ubuntu操作系统,电脑以安装Window7为主,ubuntu操作系统以虚拟系统的方式安装在电脑上。 3. 2 系统软件平台 主要用到的软件有:Linux的ubuntu操作系统,VMware Workstation软件,Window7下的记事本软件,wps软件和CodeBlocks C编程软件以及GCC编译器等等。 3. 3 系统设计 3.3.1模块设计 主要写了两个模块程序,一个是服务端程序,另一个是客户端程序,在服务端程序主要完成对服务的基本配置以及对客户端程序的一些初始化参数进行设计等,实现端用户聊天的功能。在客户端程序里,完成对客户信息的封装,可以供多个客户同时登陆,并能对错误信息给出对应的提示,方便用户使用。服务程序文件盒客户端程序文件分别为server.c和client.c,使用Gcc来调试运行成server和client文件,先启动server程序,配置服务端信息,然后启动客户端client程序,用户登陆,进行聊天。 3.3.2 服务端程序server.c主要代码如下: typedef struct { char name[10]; SA_IN address; } USER; //XXX :用户链表 typedef struct Hnode_list { USER data; struct Hnode_list *next; } Hlink, *plink; int memoryError(plink p); int creatUserList(plink head); int findUser(plink head, char name[10]); int delUser(plink head, char name[10]); int getAllUser(plink const head); int addUser(plink head, USER data); //XXX :用户链表 void ProcessLogin(char* command, SA_IN rec_addr); void ProcessChat(char* command);

linux基于socket下的简单聊天室

Linux操作系统与程序设计课程设计B报告书 姓名: 学号: 班级: 专业: 指导老师:郭玉华 计算机学院 时间:2013年7月5日

一、课程设计目的 本次课设主要是为了加强对Linux系统下的编程的各种知识点的整合与灵活运用,让我们更加熟悉Linux下的编程操作。重点在Linux下socket编程,了解TCP、UDP等协议的使用,并完成课设题目。 二、课程设计的实验环境 硬件:PC机两台以上 软件:LINUX系统 VIM编译器, Fedora 三、课程设计总体要求 1.在LINUX下实现网络聊天,包括公聊、一对多私聊等功能; 2.实现客户端之间经网络传输文件; 3.保存聊天记录,以备必要时查询。 系统功能 系统主要实现4大聊天室功能: 1.注册与登录系统 2.公聊 3.私聊 4.文件传输 模块调用关系 各模块间调用关系如图2-2所示:

图2-2 各模块间调用关系功能需求与系统模块的关系 实现原理 一、注册、登陆实现原理服务器端 服务器端建立好socket,等待连接,当客户端连接服务器,服务器接收连接,并接受客户端发送过来的消息,根据接收到的结构体所携带的协议来做相应的功能。服务器端启动后如图3-1所示: 图3-1 服务器端界面 1、注册:如果协议为reg,则为客户端注册,首先将发送过来的结构体,提取用户名和密码,然后需要对用户名合法性检验,验证之后如果用户名合法则将用户信息保存到文件中,合法性的规则包括用户名不能重复和不能使用all等协议作为用户名,并且用户名和密码都不能为空。如果注册成功,服务器端发送一个消息给注册的客户端,同样将消息保存在一个结构体里。如果失败,也给客户端发送一个消息如“您输入的用户名不能为all”或者“用户名XX已经存在”。注册结果如图3-2所示。 图3-2 注册新用户

基于Linux的socket编程的聊天室设计

TCP/IP实验报告基于Linux的socket编程的聊天室设计 2014/1/16

一、实验目的 基于Socket 套接口,实现聊天程序的设计与实现,增强程序编写能力,了解基于socket的程序设计方法,加深对计算机网络通信的理解。另外,通过课程设计培养自己严谨的科学态度,认真的工作作风、团队协作精神、自主设计和独力思考的能力。 二、实验原理 实验中,客户应用程序向服务器程序请求服务。服务进程一直处于休眠状态,直到一个客户向这个服务的地址提出了连接请求。在这个时刻,服务程序被"惊醒"并且为客户提供服务-对客户的请求作出适当的反应。 客户端部分: 1.手动输入服务器端IP地址和端口号进行连接 2.发送消息给服务器端并显示服务器端回传的消息 3.监控连接状态,客户离开或故障时从列表中删除相应表项,并及时更新连接 表。 服务器端部分: 1.手动建立服务器端与客户端的连接请求 2.把用户输入的信息及时发送到服务端,同时准备好接受,并显示信息。 3.在用户退出时关闭连接并保存聊天记录。 客户端-服务器端架构:

相关函数: socket()函数: int socket(int family,int type,int proto); 1) family 指定protocol family (PF_INET 对应TCP/IP). 2) type 指定服务类型(SOCK_STREAM, SOCK_DGRAM). 3) protocol 指定协议(通常0, 代表缺省值). bind()函数:

给socket 绑定一个地址. int bind( int sockfd, const struct sockaddr *myaddr, socklen_t addrlen); bind 返回值 listen()函数: accept()函数: int accept( int sockfd,struct sockaddr* cliaddr, socklen_t *addrlen); sockfd 是被动模式的TCP socket. cliaddr 指针,指向一个已分配好的空间. 返回客户地址. addrlen 是一个value-result参数 必须设置为cliaddr 的空间大小

Linux课程设计(Socket通讯)

Linux操作系统与程序设计课程设计指导书 安徽工业大学计算机学院

一、实验目的: 《Linux操作系统课程设计》是一门在课程《Linux操作系统与程序设计》后独立开设的实验课程。这一门实验课程的开设目的是为了通过学生独立完成一个基于Linux平台的较大型应用程序,巩固课堂上学到的Linux平台上的编程规范、技术和技巧,培养学生的编写较大型程序的能力和提高学生综合应用素质。 本课程设计实验主要围绕Linux平台上主流的基础技术展开,这些技术包括:Linux的进程、线程通信和同步技术;Mysql数据库访问技术;socket网络通信技术;图形界面(gnome)技术等,这些技术集中体现并应用在一个较大型程序------基于Linux的网络即时通信工具设计和开发中。我们期望通过这个较大型程序的设计与开发,培养学生从事大型软件开发的能力,加强学生作为软件开发团队的一员的协作精神和素质,并为将来毕业从事UNIX/Linux平台开发、嵌入式开发等相对高端的软件开发工作打下基础。 二、适应专业:计算机科学和技术专业、软件工程、网络工程 三、实验学时:40学时 四、实验内容及学时安排: 学生的设计和开发工作始于阅读和理解教师提供的框架程序,框架程序主要包括3个部分:Linux文本界面下的网络通信示例程序,Linux下利用C语言访问Mysql数据库的示例程序,Linux下gnome图形界面窗口示例程序。学生在理解和掌握这些示例程序中包含的技术基础之上,将这些技术融合在一个较大型程序------基于Linux的网络即时通信工具设计和开发中。要求前台基于Linux下的gnome图形环境并界面友好,后台使用Mysql数据库,网络通信利用socket 技术。实验的结果不仅应提交可以运行的二进制代码和源程序还应该包括完善的程序文档和数据等软件配置说明。

相关主题
相关文档
最新文档