Linux 网络编程四(socket多线程升级版)
//网络编程--客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h> #include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h> /*
强调:当客户端连接服务器时,服务器会产生一个新的文件描述符(套接字)与客户端交互,这个新的套接字不是服务器端的监听套接字
套接字是全双工的,在一个网络管道中的两端,每端都可以进行读写操作。
*/ typedef struct _recvmodel
{
int st;
struct sockaddr_in * addr;
} RecvModel; //send message
void * send_thread(void *arg)
{
if (arg == NULL)
{
printf("param is not allow NULL!\n");
return NULL;
}
int st = *(int *) arg;
char buf[] = { };
while ()
{
read(STDIN_FILENO, buf, sizeof(buf));
if (send(st, buf, strlen(buf), ) == -)
{
printf("send failed ! error message %s\n", strerror(errno));
return NULL;
}
memset(buf, , sizeof(buf));
}
return NULL;
} //recv message
void * recv_thread(void * arg)
{
if (arg == NULL)
{
printf("param is not allow NULL!\n");
return NULL;
}
RecvModel * model = (RecvModel *) arg;
int flag = ;
char buf[] = { };
while ()
{
flag = recv(model->st, buf, sizeof(buf), );
if (flag == )
{
printf("对方已经关闭连接!\n");
return NULL;
} else if (flag == -)
{
printf("recv failed ! error message : %s\n", strerror(errno));
return NULL;
}
printf("from %s:%s", inet_ntoa(model->addr->sin_addr), buf);
memset(buf, , sizeof(buf));
}
return NULL;
} int main(int arg, char *args[])
{
//打开socket
int st = socket(AF_INET, SOCK_STREAM, );
if (st == -)
{
printf("open socket failed! error message:%s\n", strerror(errno));
return -;
}
//定义IP地址结构
struct sockaddr_in addr;
memset(&addr, , sizeof(addr));
//设置TCP/IP连接
addr.sin_family=AF_INET;
//设置端口号
addr.sin_port = htons();
//设置允许连接地址
addr.sin_addr.s_addr = inet_addr("192.168.1.102");
//connect server
int numx = connect(st, (struct sockaddr *) &addr, sizeof(addr));
if (numx == -)
{
printf("connect server failed ! error message :%s\n", strerror(errno));
goto END;
} RecvModel model;
model.st = st;
model.addr = &addr;
//开启多线程--线程1接收消息,线程2发送消息
pthread_t thr1, thr2;
if (pthread_create(&thr1, NULL, send_thread, &st) != )
{
printf("create thread failed ! \n");
goto END;
}
if (pthread_create(&thr2, NULL, recv_thread, &model) != )
{
printf("create thread failed ! \n");
goto END;
}
pthread_join(thr1, NULL);
pthread_join(thr2, NULL);
END: close(st);
return ;
}
//网络编程--服务端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h> #include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h> typedef struct _recvmodel
{
int st;
struct sockaddr_in * addr;
} RecvModel; //send message
void * send_thread(void *arg)
{
if (arg == NULL)
{
printf("param is not allow NULL!\n");
return NULL;
}
int st = *(int *) arg;
char buf[] = { };
while ()
{
read(STDIN_FILENO, buf, sizeof(buf));
if (send(st, buf, strlen(buf), ) == -)
{
printf("send failed ! error message %s\n", strerror(errno));
return NULL;
}
memset(buf, , sizeof(buf));
}
return NULL;
} //recv message
void * recv_thread(void * arg)
{
if (arg == NULL)
{
printf("param is not allow NULL!\n");
return NULL;
}
RecvModel * model = (RecvModel *) arg;
int flag = ;
char buf[] = { };
while ()
{
flag = recv(model->st, buf, sizeof(buf), );
if (flag == )
{
printf("对方已经关闭连接!\n");
return NULL;
} else if (flag == -)
{
printf("recv failed ! error message : %s\n", strerror(errno));
return NULL;
}
printf("from %s:%s", inet_ntoa(model->addr->sin_addr), buf);
memset(buf, , sizeof(buf));
}
return NULL;
} int main(int arg, char *args[])
{ //short port = atoi(args[1]);
//打开socket
int st = socket(AF_INET, SOCK_STREAM, );
if (st == -)
{
printf("open socket failed! error message:%s\n", strerror(errno));
return -;
}
//设置系统地址可重用
int on = ;
if (setsockopt(st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -)
{
printf("setsockpot failed ! error message %s\n", strerror(errno));
goto END;
}
//定义IP地址结构
struct sockaddr_in addr;
memset(&addr, , sizeof(addr));
//设置TCP/IP连接
addr.sin_family = AF_INET;
//设置端口号
addr.sin_port = htons();
//设置允许连接地址
addr.sin_addr.s_addr = htonl(INADDR_ANY);
//bind ip
if (bind(st, (struct sockaddr *) &addr, sizeof(addr)) == -)
{
printf("bind ip failed ! error message :%s\n", strerror(errno));
goto END;
}
//监听连接
if (listen(st, ) == -)
{
printf("listen failed ! error message :%s\n", strerror(errno));
goto END;
}
//接收客户端连接(阻塞)
struct sockaddr_in client_addr;
memset(&client_addr, , sizeof(client_addr));
socklen_t client_addrlen = sizeof(client_addr);
//强调:这里的client_addrlen并不是为了在函数中设置client_addrlen的值,而是通过client_addrlen的值来判断client_addr是一个什么类型的结构,
//所以这里client_addrlen设置为0是错误的,必须是struct sockaddr_in这个结构的大小,不然返回值不正确
int client_st = accept(st, (struct sockaddr *) &client_addr,
&client_addrlen);
if (client_st == -)
{
printf("accept failed ! error message :%s\n", strerror(errno));
goto END;
}
RecvModel model;
model.st = client_st;
model.addr = &client_addr;
printf("accept by=%s\n",inet_ntoa(client_addr.sin_addr));
//开启多线程--线程1接收消息,线程2发送消息
pthread_t thr1, thr2;
if (pthread_create(&thr1, NULL, send_thread, &client_st) != )
{
printf("create thread failed ! \n");
goto END;
}
if (pthread_create(&thr2, NULL, recv_thread, &model) != )
{
printf("create thread failed ! \n");
goto END;
}
pthread_join(thr1, NULL);
pthread_join(thr2, NULL);
//关闭客户端管道
close(client_st);
END: close(st);
return ;
}
.SUFFIXES:.c .o
CC=gcc
SRCS1=mserver.c
SRCS2=mclient.c
OBJS1=$(SRCS1:.c=.o)
OBJS2=$(SRCS2:.c=.o)
EXEC1=mserv
EXEC2=mcli start:$(OBJS1) $(OBJS2)
$(CC) -o $(EXEC1) $(OBJS1) -lpthread
$(CC) -o $(EXEC2) $(OBJS2) -lpthread
@echo "^_^ ------ OK ------ ^_^"
.c.o:
$(CC) -Wall -g -o $@ -c $<
clean:
rm -f $(OBJS1)
rm -f $(OBJS2)
rm -f $(EXEC1)
rm -f $(EXEC2)
小结:这段升级版程序花费3小时,出现一个错误提示:" Transport endpoint is not connected",我仔细查找资料,
网上说是socket套接字不对,可我程序中套接字是正确的,
我没有办法,但是我有一个成功的程序,就是第一版socket程序,我将原来的socket程序复制到我的新程序中,一句句替换,终于发现这个问题
问题:我缺少addr.sin_family = AF_INET;//将网络地址类型设置为TCP/IP协议;这句代码。缺少这段代码是导致报错的主要原因。
另外注意我代码中强调的内容--网络管道是全双工的

Linux 网络编程四(socket多线程升级版)的更多相关文章
- linux网络编程-(socket套接字编程UDP传输)
今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中, ...
- Linux网络编程(四)
在linux网络编程[1-3]中,我们编写的网络程序仅仅是为了了解网络编程的基本步骤,实际应用当中的网络程序并不会用那样的.首先,如果服务器需要处理高并发访问,通常不会使用linux网络编程(三)中那 ...
- Linux网络编程3——socket
宏定义 首先介绍两个宏定义,看如下代码 代码1 /************************************************************************* & ...
- Linux网络编程:socket文件传输范例
基于TCP流协议的socket网络文件传输Demo: 实现:C语言功能:文件传输(可以传任何格式的文件) /********************************************** ...
- Linux网络编程四、UDP,广播和组播
一.UDP UDP:是一个支持无连接的传输协议,全称是用户数据包协议(User Datagram Protocol).UDP协议无需像TCP一样要建立连接后才能发送封装的IP数据报,也是因此UDP相较 ...
- linux网络编程(socket)之面向连接(TCP/IP)
1.流程 服务器: 创建socket: 绑定端口: 监听: 监听到有连接请求,接受请求: 建立连接,开始对话. 客户端: 创建socket: 请求建立连接: 连接建立成功,开始对话. 2.实例代码 / ...
- Linux网络编程socket选项之SO_LINGER,SO_REUSEADDR
from http://blog.csdn.net/feiyinzilgd/article/details/5894300 Linux网络编程中,socket的选项很多.其中几个比较重要的选项有:SO ...
- Linux网络编程:UDP Socket编程范例
TCP协议提供的是一种可靠的,复杂的,面向连接的数据流(SOCK_STREAM)传输服务,它通过三段式握手过程建立连接.TCP有一种"重传确认"机制,即接收端收到数据后要发出一个肯 ...
- linux网络编程之socket编程(四)
经过两周的等待,终于可以回归我正常的学习之旅了,表哥来北京了在我这暂住,晚上回家了基本在和他聊天,周末带他在北京城到处乱转,几乎剥夺了我自由学习的时间了,不过,亲人之情还是很难得的,工作学习并不是生活 ...
随机推荐
- UWP开发-HTTP详解
HTTP作为一个基础功能,有必要介绍下在UWP下的使用方法. 一.Get请求: 一般我们用到的是GetAsync方法 public static async Task Gets(Uri uri) { ...
- 分析实现Android自定义View之扇形图
继承View基类,画了这样的扇形图 直接来步骤吧 (参考了GcsSloop的教程) 1.分析 自定义View需要认真的分析下,里面还是会用到一些数学知识 首先是扇形该怎么表现 1. 扇形的外观是个圆弧 ...
- dig与dns基本理论——解析和缓存
DNS(Domain Name System,域名系统)也许是我们在网络中最常用到的服务,它把容易记住的域名,如 www.google.com 翻译成人类不易记住的IP地址,如 173.194.127 ...
- rails开发demo(一)搭建环境
环境 ubuntu 14.04 为了安装rails4.2 和 ruby 2.2.2,这是目前稳定的最新版本,需要先安装rvm sudo apt-get update sudo apt-get inst ...
- PE文件结构部分解析以及输入的定位
原文链接地址:http://www.cnblogs.com/shadow-lei/p/3554670.html PE文件定义 PE 文件("Portable executable" ...
- oracle树操作(select start with connect by prior)
oracle中的递归查询可以使用:select .. start with .. connect by .. prior 下面将会讲述oracle中树形查询的常用方式,只涉及到一张表. 一. 建表语句 ...
- IE6/7/8不支持jQuery创建非闭合格式的链接A
代码如下 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <scri ...
- 开启mysql慢查询
Linux查看mysql 安装路径一.查看文件安装路径由于软件安装的地方不止一个地方,所有先说查看文件安装的所有路径(地址).这里以mysql为例.比如说我安装了mysql,但是不知道文件都安装在哪些 ...
- Linux Bash shell one practice : array if else
shell practice 1 1.require A B C D 1 2 3 4 5 6 7 8 3 5 8 0 1 2 4 3 after handling: T A B C D A 1 2 3 ...
- java操作excel文件
采用POI操作excel API:http://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFCell.html poi包:http ...