linux面向连接的套接字编程

更新时间:2023-06-03 05:47:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

1.本实验完成面向链接的套接字,并且进行通信。

2.面向链接的套接字的工作流程;

3.服务器先用socket函数来建立一个套接字,用这个套接字完成通信的监听。

4.用bind函数来绑定一个端口号和IP地址。因为本地计算机可能有多个网址和IP,每一个IP

和端口有多个端口。需要指定一个IP和端口进行监听。

5.服务器调用listen函数,使服务器的这个端口和IP处于监听状态,等待客户机的连接。

6.客户机用socket函数建立一个套接字,设定远程IP和端口。

7.客户机调用connect函数连接远程计算机指定的端口。

8.服务器用accept函数来接受远程计算机的连接,建立起与客户机之间的通信。

9.建立连接以后,客户机用write函数向socket中写入数据。也可以用read函数读取服务器

发送来的数据。

10.服务器用read函数读取客户机发送来的数据,也可以用write函数来发送数据。

11.完成通信以后,用close函数关闭socket连接。

12.客户机与服务器建立面向连接的套接字进行通信。

实验结果截图:

详细步骤:

1.绑定描述:

函数bind可以将一个端口绑定到一个已经建立的socket上,这个函数的使用方法如下所示。 int bind(int sockfd,struct sockaddr * my_addr,int addrlen);

参数列表中,sockfd是已经建立的socket编号。sockaddr是一个指向sockaddr结构体类型的

指针。sockaddr的定义方法如下所示。

struct sockaddr

{

unsigned short int sa_family;

char sa_data[14];

};

2.监听函数:

listen函数用于实现监听等待功能。这个函数的使用方法如下所示。

int listen(int s,int backlog);

在参数列表中,s是已经建立的socket。backlog是能同时处理的最大连接请求。如

果超过这个数目,客户端将会接收到ECONNREFUSED拒绝连接的错误。

3.接受链接请求函数:

接受连接请求的函数是accept,这个函数的使用方法如下所示。

int accept(int s,struct sockaddr * addr,int * addrlen);

在参数列表中,s是处于监听状态的socket。addr是一个sockaddr结构体类型的指针,系统

会把远程主机的这些信息保存到这个结构体指针上。addrlen是sockaddr的内存长度,可以

用sizeof函数来取得。

4.请求链接函数:

connect函数可以完成请求连接的功能,这个函数的使用方法如下所示。

int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);

在参数列表中,sockfd是已经建立的socket。serv_addr是一个结构体指针,指向一个

sockaddr结构体。这个结构体存储着远程服务器的IP与端口信息。addrlen是sockaddr结构

体的内存长度,可以用sizeof函数来获取。

5.接受发来的数据函数:

函数recv可以接收远程主机发送来的数据,并把这些数据保存到一个数组中。该函数的使用

方法如下所示。

int recv(int s,void *buf,int len,unsigned int flags);

在参数列表中,s是已经建立的socket。buf是一个指针,指向一个数组。接收到的数据会保

存到这个数组上。len是数组的长度,可以用sizeof函数来取得。

6.信息发送函数send:

用connect函数连接到远程计算机以后,可以用send函数将信息发送到对方的计算机。这个

函数的使用方法如下所示。

int send(int s,const void * msg,int len,unsigned int flags);

在参数列表中,s是已经建立的socket。msg是需要发送数据的指针。len是需要发送数据的

长度。这个长度可以用sizeof函数来取得。

7.信息发送函数和读取函数:

数据传输函数write与read:在前面的章节讲述过,write函数可以向文件中写入数据,read

函数可以从文件中读取数据。socket建立连接以后,向这个socket中写入数据表示向远程主

机传送数据。从socket中读取数据相关于接受远程主机传送过来的数据。这两个函数的使用

方法如下所示。

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

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

在参数列表中,fd是已经建立的socket。buf是指向一段内存的指针,count表示buf指向内

存的长度。read函数读取字节时,会把读取的内容保存到buf指向的内存中,然后返回读取

到字节的个数。使用write函数传输数据时,会把buf指针指向的内存中的数据发送到socket

连接的远程主机,然后返回实际发送字节的个数。

服务端代码:

#include<sys/types.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

#include<unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <strings.h>

#include <fcntl.h>

#include <string.h>

#define PORT 5678

int main()

{

int sockfd,newsockfd,fd;

struct sockaddr_in addr;

int addr_len = sizeof(struct sockaddr_in);

char msgbuffer[10000];

char tmp_file[128], file[128];

ssize_t bytes;

if ((sockfd = socket(AF_INET,SOCK_STREAM,0))<0)

{

perror("create socket");

return 0;

}

bzero(&addr,sizeof(addr));

addr.sin_family =AF_INET;

addr.sin_port = htons(PORT);

addr.sin_addr.s_addr = htonl(INADDR_ANY);

if(bind(sockfd,(struct sockaddr*)&addr,sizeof(addr))<0)

{

perror("bind socket");

return 0;

if(listen(sockfd,3)<0)

{

perror("listen");

return 0;

}

if((newsockfd = accept (sockfd,(struct sockaddr*)&addr,&addr_len))<0)

{

perror("accept");

return 0;

}

while(1)

{

bytes = recv(newsockfd, msgbuffer, sizeof(msgbuffer),0);

if (bytes<=0)

break;

else if (!strncmp(msgbuffer, "filename", 8))

{

sscanf(msgbuffer, "filename:%s", tmp_file);

printf("the file name which client send is %s\n", tmp_file);

sprintf(file, "/tmp/%s", tmp_file);

fd = open(file, O_CREAT|O_WRONLY);

if (fd>0)

{

printf("open file %s ok!\n", file);

strcpy(msgbuffer, "accepted");

write(newsockfd, msgbuffer, sizeof(msgbuffer));

}

}

else

write(fd, msgbuffer, bytes);

}

printf("%s wrote ok!\n", file);

if (fd>0)

close(fd);

close(newsockfd);

close(sockfd);

return 0;

}

客户端代码:

#include<sys/types.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

#include<unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <fcntl.h>

#define PORT 5678

int main(int argc, char *argv[])

{

int sockfd,fd;

struct sockaddr_in addr;

int addr_len = sizeof(struct sockaddr_in);

char msgbuffer[10000];

ssize_t bytes;

if (argc<2)

{

printf("input file name please!\n");

return 0;

}

if ((sockfd = socket(AF_INET,SOCK_STREAM,0))<0)

{

perror("create socket");

return 0;

}

bzero(&addr,sizeof(addr));

addr.sin_family =AF_INET;

addr.sin_port = htons(PORT);

addr.sin_addr.s_addr = htonl(INADDR_ANY);

if (connect(sockfd, (struct sockaddr*)&addr, addr_len)<0)

{

perror("connect");

return 0;

}

sprintf(msgbuffer, "filename:%s", argv[1]);

write(sockfd, msgbuffer, strlen(msgbuffer));

read(sockfd, msgbuffer, sizeof(msgbuffer));

if (!strncmp(msgbuffer, "accepted", 8))

{

fd = open(argv[1], O_RDONLY);

printf("file %s opened!\n", argv[1]);

if (fd>0)

{

while((bytes=read(fd, msgbuffer, sizeof(msgbuffer))>0))

{

send(sockfd, msgbuffer, bytes,0);

}

close(fd);

printf("send file to server ok!\n");

}

}

write(sockfd, msgbuffer, strlen(msgbuffer));

close(sockfd);

return 0;

}

调试过程:

服务器端:

1.用于保存字符的数组给的空间太少,修改为10000后,恢复正常;

2.在接受请求之后没有关闭socket;

3.读取字符的时候用错了函数名字;

客户端:

1.链接的时候套接字的判断条件错误;

总结体会:

一:个人总结:

1.对面向链接的套接字通信有了新的认识;

2.发现在写实验时候还是好多东西不会写,需要翻课本,需要请教同学;

3.好多东西上课听下就很容易学会了,但是不上心,需要下去下很大的功夫才能完成。 二:知识点总结:

1.绑定描述:

函数bind可以将一个端口绑定到一个已经建立的socket上,这个函数的使用方法如下所示。 int bind(int sockfd,struct sockaddr * my_addr,int addrlen);

参数列表中,sockfd是已经建立的socket编号。sockaddr是一个指向sockaddr结构体类型的

指针。sockaddr的定义方法如下所示。

struct sockaddr

{

unsigned short int sa_family;

char sa_data[14];

};

2.监听函数:

listen函数用于实现监听等待功能。这个函数的使用方法如下所示。

int listen(int s,int backlog);

在参数列表中,s是已经建立的socket。backlog是能同时处理的最大连接请求。如

果超过这个数目,客户端将会接收到ECONNREFUSED拒绝连接的错误。

3.接受链接请求函数:

接受连接请求的函数是accept,这个函数的使用方法如下所示。

int accept(int s,struct sockaddr * addr,int * addrlen);

在参数列表中,s是处于监听状态的socket。addr是一个sockaddr结构体类型的指针,系统

会把远程主机的这些信息保存到这个结构体指针上。addrlen是sockaddr的内存长度,可以

用sizeof函数来取得。

4.请求链接函数:

connect函数可以完成请求连接的功能,这个函数的使用方法如下所示。

int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);

在参数列表中,sockfd是已经建立的socket。serv_addr是一个结构体指针,指向一个

sockaddr结构体。这个结构体存储着远程服务器的IP与端口信息。addrlen是sockaddr结构

体的内存长度,可以用sizeof函数来获取。

5.接受发来的数据函数:

函数recv可以接收远程主机发送来的数据,并把这些数据保存到一个数组中。该函数的使用

方法如下所示。

int recv(int s,void *buf,int len,unsigned int flags);

在参数列表中,s是已经建立的socket。buf是一个指针,指向一个数组。接收到的数据会保

存到这个数组上。len是数组的长度,可以用sizeof函数来取得。

6.信息发送函数send:

用connect函数连接到远程计算机以后,可以用send函数将信息发送到对方的计算机。这个

函数的使用方法如下所示。

int send(int s,const void * msg,int len,unsigned int flags);

在参数列表中,s是已经建立的socket。msg是需要发送数据的指针。len是需要发送数据的

长度。这个长度可以用sizeof函数来取得。

7.信息发送函数和读取函数:

数据传输函数write与read:在前面的章节讲述过,write函数可以向文件中写入数据,read

函数可以从文件中读取数据。socket建立连接以后,向这个socket中写入数据表示向远程主

机传送数据。从socket中读取数据相关于接受远程主机传送过来的数据。这两个函数的使用

方法如下所示。

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

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

在参数列表中,fd是已经建立的socket。buf是指向一段内存的指针,count表示buf指向内

存的长度。read函数读取字节时,会把读取的内容保存到buf指向的内存中,然后返回读取

到字节的个数。使用write函数传输数据时,会把buf指针指向的内存中的数据发送到socket

连接的远程主机,然后返回实际发送字节的个数。

本文来源:https://www.bwwdw.com/article/42s1.html

Top