Linux下C语言的socket网络编程

来源(博客园)

From: https://www.cnblogs.com/uestc-mm/p/7630145.html

Linux下C语言的socket网络编程

关于详细的服务器建立的步骤以及相关的socket套接字的知识我已经在python socket编程的文章中提到过了,大家可以参看那一篇博客来历接socket套接字编程的内容,由于要是用C相关的API所以这里采用了基于C语言的socket API编写相关的网络编程内容,具体的实现如下所示,调试通过。文章链接:http://www.cnblogs.com/uestc-mm/p/7296083.html

服务端Server.c程序内容:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/************************************************************************************************************************
1、int socket(int family,int type,int protocol)
family:
	指定使用的协议簇:AF_INET(IPv4) AF_INET6(IPv6) AF_LOCAL(UNIX协议) AF_ROUTE(路由套接字) AF_KEY(秘钥套接字)
type:
	指定使用的套接字的类型:SOCK_STREAM(字节流套接字) SOCK_DGRAM
protocol:
	如果套接字类型不是原始套接字,那么这个参数就为0
2、int bind(int sockfd, struct sockaddr *myaddr, int addrlen)
sockfd:
	socket函数返回的套接字描述符
myaddr:
	是指向本地IP地址的结构体指针
myaddrlen:
	结构长度
struct sockaddr{
	unsigned short sa_family; //通信协议类型族AF_xx
	char sa_data[14];  //14字节协议地址,包含该socket的IP地址和端口号
};
struct sockaddr_in{
	short int sin_family; //通信协议类型族
	unsigned short int sin_port; //端口号
	struct in_addr sin_addr; //IP地址
	unsigned char si_zero[8];  //填充0以保持与sockaddr结构的长度相同
};
3、int connect(int sockfd,const struct sockaddr *serv_addr,socklen_t addrlen)
sockfd:
	socket函数返回套接字描述符
serv_addr:
	服务器IP地址结构指针
addrlen:
	结构体指针的长度
4、int listen(int sockfd, int backlog)
sockfd:
	socket函数绑定bind后套接字描述符
backlog:
	设置可连接客户端的最大连接个数,当有多个客户端向服务器请求时,收到此值的影响。默认值20
5、int accept(int sockfd,struct sockaddr *cliaddr,socklen_t *addrlen)
sockfd:
	socket函数经过listen后套接字描述符
cliaddr:
	客户端套接字接口地址结构
addrlen:
	客户端地址结构长度
6、int send(int sockfd, const void *msg,int len,int flags)
7、int recv(int sockfd, void *buf,int len,unsigned int flags)
sockfd:
	socket函数的套接字描述符
msg:
	发送数据的指针
buf:
	存放接收数据的缓冲区
len:
	数据的长度,把flags设置为0
*************************************************************************************************************************/
int main(int argc, char *argv[])
{
	int fd, new_fd, struct_len, numbytes,i;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
	char buff[BUFSIZ];

	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(8000);
	server_addr.sin_addr.s_addr = INADDR_ANY;
	bzero(&(server_addr.sin_zero), 8);
	struct_len = sizeof(struct sockaddr_in);

	fd = socket(AF_INET, SOCK_STREAM, 0);
	while(bind(fd, (struct sockaddr *)&server_addr, struct_len) == -1);
	printf("Bind Success!\n");
	while(listen(fd, 10) == -1);
	printf("Listening....\n");
	printf("Ready for Accept,Waitting...\n");
	new_fd = accept(fd, (struct sockaddr *)&client_addr, &struct_len);
	printf("Get the Client.\n");
	numbytes = send(new_fd,"Welcome to my server\n",21,0);
	while((numbytes = recv(new_fd, buff, BUFSIZ, 0)) > 0)
	{
		buff[numbytes] = '\0';
		printf("%s\n",buff);
		if(send(new_fd,buff,numbytes,0)<0)
		{
			perror("write");
			return 1;
		}
	}
	close(new_fd);
	close(fd);
	return 0;
}


客户端Client.c程序内容:

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

int main(int argc,char *argv[])
{
	int sockfd,numbytes;
	char buf[BUFSIZ];
	struct sockaddr_in their_addr;
	printf("break!");
	while((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1);
	printf("We get the sockfd~\n");
	their_addr.sin_family = AF_INET;
	their_addr.sin_port = htons(8000);
	their_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
	bzero(&(their_addr.sin_zero), 8);

	while(connect(sockfd,(struct sockaddr*)&their_addr,sizeof(struct sockaddr)) == -1);
	printf("Get the Server~Cheers!\n");
	numbytes = recv(sockfd, buf, BUFSIZ,0);//接收服务器端信息
	buf[numbytes]='\0';
	printf("%s",buf);
	while(1)
	{
		printf("Entersome thing:");
		scanf("%s",buf);
		numbytes = send(sockfd, buf, strlen(buf), 0);
		numbytes=recv(sockfd,buf,BUFSIZ,0);
		buf[numbytes]='\0';
		printf("received:%s\n",buf);
	}
	close(sockfd);
	return 0;
}


复制代码

使用gcc编译器对客户端程序和服务端程序进行编译和解释:

gcc -o Master Server.c
gcc -o Slave Client.c


编译的结果如下所示:



这时请先运行Master程序,然后再运行Slave程序:



在客户端Client输入要发送的内容:



Q1:我们需要注意在Client端使用scanf函数让客户输入信息的时候使用的是scanf("%s",buf),若是使用的是scanf("%s\n",buf),这就会导致服务端输出的结果比客户端输入的内容滞后一次,大家可以实验一下~具体的原因参考:http://www.cnblogs.com/uestc-mm/p/7644370.html

Q2:在编写服务端程序的过程中,我使用的是while((numbytes = recv(new_fd, buff, BUFSIZ, 0)) != -1)来等待数据的接收,似乎是有问题的,结果就是一直得不到想要的输出,所以改成while((numbytes = recv(new_fd, buff, BUFSIZ, 0)) > 0)就可以了,具体的原因也不清楚了~后面在实验一下,纪录在此~

完~

感谢GISPALAB实验室的老师和同学们的帮助和支持~

Link: http://www.asm32.net/article_details.aspx?id=7303


浏览次数 0 发布时间 2018/5/4 17:15:03 从属分类 C/C++ 【评论】【 】【打印】【关闭
 
| www.asm32.net | 2006版 | 资料中心 | linux | asm/asm32 | C/C++ | VC++ | java | Python | 书签 | ASP.Net书签 | 京ICP备09029108号-1