要实现一个服务器,其实主要是对socket编程的理解。这里运用到了Socket编程的面向连接的编程,其流程如下:
下面直接贴代码了。
1、服务器端程序
(1)代码
/**
* @file : tcpserver.c
* @brief: A simple Tcp server
* @author: ToakMa <mchgloak1120@163.com>
* @date: 2014/10/09
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <strings.h>
#include <arpa/inet.h>
#define PORT 9000
#define WAIT_QUEUE_LEN 5
#define BUFF_SIZE 1024
#define WELCOME "### Welcome to my server ^_^! ###\n"
int main(int argc, char *argv[])
{
int serverfd, clientfd;
struct sockaddr_in saddr;
struct sockaddr_in caddr;
socklen_t c_addrlen;
int res;
int len;
char buff[BUFF_SIZE];
//1. create socket
serverfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == serverfd)
{
perror("server socket : ");
return -1;
}
printf("server socket create succ!\n");
//2. prepare IP and port
//memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(PORT);
saddr.sin_addr.s_addr = INADDR_ANY;
//inet_aton("192.168.0.100", &(saddr.sin_addr));
bzero(&(saddr.sin_zero), 8);
//3. bind
res = bind(serverfd, (struct sockaddr *)&saddr, sizeof(struct sockaddr));
if (-1 == res)
{
perror("server bind: ");
return -1;
}
printf("bind succ!\n");
//4. listen
res = listen(serverfd, WAIT_QUEUE_LEN);
if (-1 == res)
{
perror("server listen : ");
return -1;
}
printf("server listen...\n");
//5. accept
c_addrlen = sizeof(struct sockaddr_in);
clientfd = accept(serverfd, (struct sockaddr *)&caddr, &c_addrlen);
if (-1 == clientfd)
{
perror("server accept: ");
return -1;
}
printf("server have a client, IP: %s \n", inet_ntoa(caddr.sin_addr));
//6.send a welcome
send(clientfd, WELCOME, strlen(WELCOME), 0);
//7. interactive
while ((len = recv(clientfd, buff, BUFF_SIZE, 0)) > 0)
{
buff[len] = '\0';
printf("recv msg is : %s \n", buff);
if (send(clientfd, buff, len, 0) < 0)
{
perror("server send: ");
return -1;
}
}
//8. close
close(clientfd);
close(serverfd);
return 0;
}
(2)程序理解:
通过socket()函数创建了一个套接字,然后将套接字绑定到主机所有本地地址的TCP端口9000上。接着listen()系统调用创建5个等待队列,等待客户端连接请求的到达。当一个连接请求到达时,accept系统调用会返回一个新的套接字描述符,用来描述远程的客户端连接。原来的套接字仍然用来接收其他客户端的请求。 然后便是一些交互:发送和接受数据的处理。最后,关闭套接字。
(3)telnet测试效果:
为了更好地理解面向连接的Socket编程模型,下面写一个客户端程序来测试。
2、客户端程序
(1)代码:
/**
* @file: tcpclient.c
* @brief: A simple Tcp client
* @author: ToakMa <mchgloak1120@163.com>
* @date: 2014/10/09
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 9000
#define BUFF_SIZE 1024
int main(int argc, char *argv[])
{
int sockfd;
int recv_len, send_len;
struct sockaddr_in remote_addr;
char buff[BUFF_SIZE];
int res;
//1. create socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("client socket :");
return -1;
}
//2. prepare ip and port
memset(&remote_addr, 0, sizeof(remote_addr));
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(PORT);
remote_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
bzero(&(remote_addr.sin_zero), 8);
//3. connect to server
res = connect(sockfd, (struct sockaddr *)&remote_addr, sizeof(remote_addr));
if (-1 == res)
{
perror("client connect: ");
return -1;
}
printf("client connect server succ!\n");
//4. recv sth
recv_len = recv(sockfd, (struct sockaddr *)&remote_addr, sizeof(remote_addr), 0);
buff[recv_len] = '\0';
printf(" %s ", buff);
//5. interactive
while (1)
{
printf("Enter string to send: ");
scanf("%s", buff);
if (!strcmp(buff, "quit"))
break;
send_len = send(sockfd, buff, strlen(buff), 0);
recv_len = recv(sockfd, buff, BUFF_SIZE, 0);
buff[recv_len] = '\0';
printf(" received: %s \n", buff);
}
//6. close
close(sockfd);
return 0;
}
(2)程序理解:
首先创建了套接字,并和本机的TCP端口9000建立连接。如果连接成功,将会受到server发来的一个welcome,然后就可以进行通信了。
(3)测试:
首先运行服务器,然后运行客户端,其运行效果如下:
代码源码地址:http://www.oschina.net/code/snippet_1241861_39180