Socket网络编程--聊天程序(1)
很早的一段时间,看了APUE和UNPv1了解了网络编程,但是但是只是看而已,没有具体的实践,趁现在没有什么事做,就来实践了解一下网络编程。写博客保存下来,方便以后用到的时候可以查到。
此次的聊天程序是迭代开发的。就是一步一步的修改成不同功能的聊天程序。
服务器server和客户端client
一对一,server和client是每人一句话聊天
讲解几个函数gethostbyname(),这个函数以前讲过就不多说了。
socket函数
#include <sys/socket.h>
int socket(int domain, int type, int protocol); //返回值:若成功则返回文件(套接字)描述符,若出错则返回-1
connect函数
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t len); //返回值:若成功则返回0,若出错则返回-1
bind函数
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t len); //返回值:若成功则返回0,若出错则返回-1
listen函数
#include <sys/socket.h>
int listen(int sockfd, int backlog); //返回值:若成功则返回0,若出错则返回-1,backlog表示连接请求数量
accept函数
#include <sys/socket.h>
int accept(int socdfd, struct sockaddr *restrict addr, socklen_t * restrict len); //若成功则返回文件(socket套接字)描述符,若出错则返回-1
recv函数
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t nbytes, int flags); //返回值:以字节计数的消息长度,若无可用消息或对方已经按序结束则返回0,若出错则返回-1
send函数
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t nbytes, int flags); //返回值:若成功则返回发送的字节数,若出错则返回-1
fgets函数
#include <stdio.h>
char *fgets(char *s, int size, FILE *stream);
介绍完函数后,就直接贴出代码。
client.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h> //for gethostbyname
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> #define MAX_BUF 4096
#define SERVER_PORT 12138 int main(int argc,char *argv[])
{
int sockfd;//socket
char sendBuf[MAX_BUF],recvBuf[MAX_BUF];
int sendSize,recvSize;//用于记录记录发送和接收到数据的大小
struct hostent * host;
struct sockaddr_in servAddr;
char username[];
char * p; if(argc != )
{
perror("use: ./client [hostname] [username]");
exit(-);
}
p=username;
strcpy(p,argv[]);
printf("username:%s\n",username);
host=gethostbyname(argv[]);
if(host==NULL)
{
perror("fail to get host by name.");
exit(-);
}
printf("Success to get host by name ...\n"); //创建socket
if((sockfd=socket(AF_INET,SOCK_STREAM,))==-)
{
perror("fail to establish a socket");
exit();
}
printf("Success to establish a socket...\n"); /*init sockaddr_in*/
servAddr.sin_family=AF_INET;
servAddr.sin_port=htons(SERVER_PORT);
servAddr.sin_addr=*((struct in_addr *)host->h_addr);
bzero(&(servAddr.sin_zero),); /*connect the socket*/
if(connect(sockfd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr_in))==-)
{
perror("fail to connect the socket");
exit();
}
printf("Success to connect the socket...\n"); //send-recv
while()
{
printf("Input:");
fgets(sendBuf,MAX_BUF,stdin);
send(sockfd,sendBuf,strlen(sendBuf),);
memset(sendBuf,,sizeof(sendBuf));
recv(sockfd,recvBuf,MAX_BUF,);
printf("Server:%s\n",recvBuf);
memset(recvBuf,,sizeof(recvBuf));
} return ;
}
server.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h> #define SERVER_PORT 12138
#define BACKLOG 20
#define MAX_CON_NO 10
#define MAX_DATA_SIZE 4096 int main(int argc,char *argv[])
{
struct sockaddr_in serverSockaddr,clientSockaddr;
char sendBuf[MAX_DATA_SIZE],recvBuf[MAX_DATA_SIZE];
int sendSize,recvSize;
int sockfd,clientfd;
int on=;
int sinSize=;
char username[]; if(argc != )
{
printf("usage: ./server [username]\n");
exit();
}
strcpy(username,argv[]);
printf("username:%s\n",username); /*establish a socket*/
if((sockfd = socket(AF_INET,SOCK_STREAM,))==-)
{
perror("fail to establish a socket");
exit();
}
printf("Success to establish a socket...\n"); /*init sockaddr_in*/
serverSockaddr.sin_family=AF_INET;
serverSockaddr.sin_port=htons(SERVER_PORT);
serverSockaddr.sin_addr.s_addr=htonl(INADDR_ANY);
bzero(&(serverSockaddr.sin_zero),); setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); /*bind socket*/
if(bind(sockfd,(struct sockaddr *)&serverSockaddr,sizeof(struct sockaddr))==-)
{
perror("fail to bind");
exit();
}
printf("Success to bind the socket...\n"); /*listen on the socket*/
if(listen(sockfd,BACKLOG)==-)
{
perror("fail to listen");
exit();
} /*accept a client's request*/
if((clientfd=accept(sockfd,(struct sockaddr *)&clientSockaddr, &sinSize))==-)
{
perror("fail to accept");
exit();
}
printf("Success to accpet a connection request...\n");
printf(" %s join in!\n",inet_ntoa(clientSockaddr.sin_addr));
while()
{
/*receive datas from client*/
if((recvSize=recv(clientfd,recvBuf,MAX_DATA_SIZE,))==-)
{
perror("fail to receive datas");
exit();
}
printf("%s\n",recvBuf);
memset(recvBuf,,MAX_DATA_SIZE); /*send datas to client*/
printf("Server:");
fgets(sendBuf,MAX_DATA_SIZE,stdin);
if((sendSize=send(clientfd,sendBuf,strlen(sendBuf),))!=strlen(sendBuf))
{
perror("fail to send datas");
exit();
}
printf("Success to send datas\n");
memset(sendBuf,,MAX_DATA_SIZE);
} return ;
}
这些代码都比较简单,详细的讲解网上都有,这里就不多说了。
本文地址: http://www.cnblogs.com/wunaozai/p/3870156.html
Socket网络编程--聊天程序(1)的更多相关文章
- Socket网络编程--聊天程序(9)
这一节应该是聊天程序的最后一节了,现在回顾我们的聊天程序,看起来还有很多功能没有实现,但是不管怎么说,都还是不错的.这一节我们将讲多服务器问题(高大上的说法就是负载问题了.)至于聊天程序的文件发送(也 ...
- Socket网络编程--聊天程序(8)
上一节已经完成了对用户的身份验证了,既然有了验证,那么接下来就能对不同的客户端进行区分了,所以这一节讲实现私聊功能.就是通过服务器对客户端的数据进行转发到特定的用户上, 实现私聊功能的聊天程序 实现的 ...
- Socket网络编程--聊天程序(6)
这一小节将增加一个用户的结构体,用于保存用户的用户名和密码,然后发给服务器,然后在服务器进行判断验证.这里就有一个问题,以前讲的就是发送字符串是使用char类型进行传输,然后在服务器进行用同样是字符串 ...
- Socket网络编程--聊天程序(7)
接上一小节,本来是计划这一节用来讲数据库的增删改查,但是在实现的过程中,出现了一点小问题,也不是技术的问题,就是在字符界面上比较不好操作.比如要注册一个帐号,就需要弄个字符界面提示,然后输入数字表示选 ...
- Socket网络编程--聊天程序(3)
上一小节,已经讲到可以每个人多说话,而且还没有限制,简单的来说,我们已经完成了聊天的功能了,那么接下来我们要实现什么功能呢?一个聊天程序至少应该支持一对多的通讯吧,接下来就实现多个客户端往服务器发送数 ...
- Socket网络编程--聊天程序(4)
上一小节讲到可以实现多客户端与服务器进行通讯,对于每一个客户端的连接请求,服务器都要分配一个进程进行处理.对于多用户连接时,服务器会受不了的,而且还很消耗资源.据说有个select函数可以用,好像还很 ...
- Socket网络编程--聊天程序(5)
上一小节我们讲了使用select来避免使用多进程的资源浪费问题.上次只是实现了从多个客户端发送数据给服务器端,接下来就要实现从服务器端发送数据给各个客户端. 使用select多路转换处理聊天程序2 c ...
- Socket网络编程--聊天程序(2)
上一节简单如何通过Socket创建一个连接,然后进行通信.只是每个人只能说一句话.而且还是必须说完才会接收到信息,总之是很不方便的事情.所以这一小节我们将对上一次的程序进行修改,修改成每个人可以多说话 ...
- Socket网络编程--小小网盘程序(5)
各位好呀!这一小节应该就是这个小小网盘程序的最后一小节了,这一节将实现最后的三个功能,即列出用户在服务器中的文件列表,还有删除用户在服务器中的文件,最后的可以共享文件给好友. 列出用户在服务器中的文件 ...
随机推荐
- Spring框架学习04——复杂类型的属性注入
代码示例如下: 创建BeanClass实体类 public class BeanClass { private String[] arrs;//数组类型 private List<String& ...
- 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-7 混合概率密度
Preface 注:鉴于很多网站随意爬取数据,可能导致内容残缺以及引用失效等问题,影响阅读,请认准原创网址: https://www.cnblogs.com/lv-anchoret/category ...
- go语言学习-接口
Go语言中虽然没有传统面向对象语言中类.集成的概念,不过提供了接口的支持,可以使用接口来使用一些面向对象的特性. 在 go 语言中,的接口有下面几个特点: 可以包含0个或多个方法的签名 只定义方法的签 ...
- 12,EasyNetQ-自动订阅
EasyNetQ自v0.7.1.30附带一个简单的AutoSubscriber. 您可以使用它轻松扫描实现接口IConsume <T>或IConsumeAsync <T>的类的 ...
- Web大前端面试题-Day9
1. 请用至少3中方式实现数组去重? 方法一: indexOfvar arr1=[1,2,3,4,5,4,3,2,1]; function repeat1(arr){ for(var i=0, ...
- 用type动态创建Form
type时所有元类的父亲object是type(object的类型是type),type也是object(type继承自object) >>> isinstance(object, ...
- 使用C3P0报错:java.lang.NoClassDefFoundError: com/mchange/v2/ser/Indirector
错误提示: java.lang.NoClassDefFoundError: com/mchange/v2/ser/Indirector at JDBC.ConnectionPool.testC3P0( ...
- Linux下如何查看系统启动时间和运行时间(转)
1.uptime命令输出:16:11:40 up 59 days, 4:21, 2 users, load average: 0.00, 0.01, 0.00 2.查看/proc/uptime文件计算 ...
- 增益 Gain 分贝 dB
https://zh.wikipedia.org/wiki/%E5%88%86%E8%B2%9D 分贝(decibel)是量度两个相同单位之数量比例的单位,主要用于度量声音强度,常用dB表示. “分” ...
- linux 启动 Oracle 实例
启动数据库实例,分为两步:第一步,启动监听:第二步,启动数据库实例. 一.如何启动数据库实例 1.进入到sqlplus启动实例 --“切换到oracle用户” su - oracle --“打开监听” ...