Linux socket编程案例

10 篇文章 0 订阅

    关于Linux网路编程的介绍,网上很多资料,这里就不赘言(详细内容可见参考资料),本文主要对创建一个简单的服务器与客户端程序进行总结。

1 Server

1.1 流程

    关于创建一个网络服务器程序的流程,参考资料[2]有总结,这里将其再现如下:

socket()-->bind()-->listen()-->accept()->write()/read()

1.2 实例

    参考资料[2]已经给出了一个比较简单而完整的服务端案例,这里将其再现如下:

/******* 服务器程序  (server.c) ************/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
	int sockfd,new_fd;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
	int sin_size, portnumber;
	char hello[] = "Hello! Are You Fine?\n";

	if( argc != 2 ) {
		fprintf(stderr,"Usage:%s portnumber\a\n", argv[0]);
		exit(1);
	}

	if( ( portnumber = atoi( argv [1] )) < 0 ){
		fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]);
		exit(1);
	}

	/* 服务器端开始建立socket描述符 */
	if( ( sockfd = socket( AF_INET, SOCK_STREAM, 0) ) == -1 ) {
		fprintf(stderr,"Socket error:%s\n\a",strerror(errno));
		exit(1);
	}

	/* 服务器端填充sockaddr结构  */ 
	bzero( &server_addr, sizeof(struct sockaddr_in) );
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = htonl( INADDR_ANY );
	server_addr.sin_port = htons( portnumber );

	/* 捆绑sockfd描述符  */ 
	if( bind( sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr))==-1) {
		fprintf( stderr, "Bind error:%s\n\a", strerror( errno ) );
		exit(1);
	}

	/* 监听sockfd描述符  */
	if( listen(sockfd,5) == -1) {
		fprintf( stderr, "Listen error:%s\n\a", strerror( errno ) );
		exit(1);
	}

	while(1)
	{
		/* 服务器阻塞,直到客户程序建立连接  */
		sin_size = sizeof(struct sockaddr_in);
		if( ( new_fd = accept( sockfd, (struct sockaddr *)(&client_addr), &sin_size )) == -1) {
			fprintf(stderr,"Accept error:%s\n\a", strerror( errno ) );
			exit( 1 );
		}

		printf("Server get connection from %s\n",
				inet_ntoa( client_addr.sin_addr ) );
		if( write( new_fd, hello, strlen( hello ) ) == -1 ) {
			fprintf( stderr, "Write Error:%s\n", strerror( errno ) );
			exit(1);
		}

		/* 这个通讯已经结束     */
		close( new_fd );
		
		/* 循环下一个     */  
	}

	close( sockfd );
	exit(0);
}

2 Client

2.1 流程

    根据参考资料[2]的说明,相对于服务器程序而言,创建一个客户端程序的流程比较简单,只需要两步即可:

socket()-->connect()-->read()/write()

2.2 实例

   参考资料[2]已经给出了一个比较简单但是完整的客户端程序,这里将其再现如下:

/******* 客户端程序  client.c ************/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
	int sockfd;
	char buffer[1024];
	struct sockaddr_in server_addr;
	struct hostent *host;
	int portnumber, nbytes;

	if( argc != 3) {
		fprintf( stderr, "Usage:%s hostname portnumber\a\n", argv[0] );
		exit(1);
	}

	if( ( host = gethostbyname( argv[1] ) ) == NULL) {
			fprintf(stderr,"Gethostname error\n");
			exit(1);
	}

	if( ( portnumber = atoi( argv[2] ) )<0) {
			fprintf( stderr, "Usage:%s hostname portnumber\a\n", argv[0] );
			exit(1);
	}

	/* 客户程序开始建立 sockfd描述符  */
	if( ( sockfd = socket( AF_INET,SOCK_STREAM, 0 ) ) == -1) {
			fprintf( stderr, "Socket Error:%s\a\n", strerror(errno) );
			exit(1);
	}

	/* 客户程序填充服务端的资料 */
	bzero( &server_addr, sizeof( server_addr ) );
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons( portnumber );
	server_addr.sin_addr = *( ( struct in_addr * )host->h_addr );

	/* 客户程序发起连接请求 */ 
	if( connect( sockfd, ( struct sockaddr * )( &server_addr ), sizeof( struct sockaddr ) ) ==-1 ) {
			fprintf(stderr, "Connect Error:%s\a\n", strerror(errno));
			exit(1);
	}

	/* 连接成功了 */
	if( ( nbytes = read(sockfd, buffer, 1024 ) ) == -1 ) {
			fprintf(stderr, "Read Error:%s\n", strerror( errno ));
			exit(1);
	}
	buffer[nbytes] = '\0';
	printf("I have received:%s\n", buffer);
	
	/* 结束通讯     */
	close( sockfd );
	exit(0);
}

参考资料

[1]Linux环境下网络编程杂谈 

[2]Linux网络编程入门

[3]Linux_套接字编程 

[4]linux套接字编程

[5]Linux网络编程之套接字

[6]套接字传输文件的试验

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OneSea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值